From 35fc3506e93d79b0ed7a3c352f88f9b5c94120db Mon Sep 17 00:00:00 2001 From: "Matteo F. Vescovi" Date: Mon, 15 Feb 2016 21:17:05 +0100 Subject: [PATCH] Imported Upstream version 0.1.16 --- INSTALL | 10 +- Makefile.in | 2 + NEWS | 4 + README | 315 ++++++++----------- babl/Makefile.in | 2 + babl/babl-cpuaccel.c | 22 +- babl/babl-cpuaccel.h | 5 + babl/babl-version.h | 2 +- babl/base/Makefile.in | 2 + babl/base/type-half.c | 128 +------- config.h.in | 6 + configure | 199 +++++++++++- configure.ac | 51 ++- docs/Makefile.in | 2 + docs/graphics/Makefile.in | 2 + docs/graphics/babl-16x16.png | Bin 505 -> 508 bytes docs/graphics/babl-48x48.png | Bin 1901 -> 1894 bytes docs/graphics/babl-a4poster.png | Bin 34780 -> 34824 bytes extensions/CIE.c | 84 +++++ extensions/Makefile.am | 12 + extensions/Makefile.in | 93 +++++- extensions/float-half.c | 356 +++++++++++++++++++++ extensions/gggl-lies.c | 179 ----------- extensions/gggl-table-lies.c | 479 +++++++++++++++++++++++++++++ extensions/gggl-table.c | 528 ++++++++++++++++++++++++++++++++ extensions/gggl.c | 232 +------------- extensions/sse-half.c | 270 ++++++++++++++++ extensions/sse2-float.c | 20 ++ extensions/sse4-int8.c | 218 +++++++++++++ tests/Makefile.in | 2 + tools/Makefile.in | 2 + 31 files changed, 2480 insertions(+), 747 deletions(-) create mode 100644 extensions/float-half.c create mode 100644 extensions/gggl-table-lies.c create mode 100644 extensions/gggl-table.c create mode 100644 extensions/sse-half.c create mode 100644 extensions/sse4-int8.c diff --git a/INSTALL b/INSTALL index ea794e3..c617fd1 100644 --- a/INSTALL +++ b/INSTALL @@ -1,5 +1,5 @@ -babl 0.1.14 +babl 0.1.16 Dynamic; any to any, pixel format conversion library. @@ -12,10 +12,10 @@ From a released version the following is the expected method of installation (or a variation on this theme): ------------------------------------------------------------ - foo$ wget ftp://ftp.gtk.org/pub/babl/0.1/babl-0.1.14.tar.bz2 - foo$ tar jxf babl-0.1.14.tar.gz - foo$ cd babl-0.1.14 - foo/babl-0.1.14$ ./configure && make && sudo make install + foo$ wget ftp://ftp.gtk.org/pub/babl/0.1/babl-0.1.16.tar.bz2 + foo$ tar jxf babl-0.1.16.tar.gz + foo$ cd babl-0.1.16 + foo/babl-0.1.16$ ./configure && make && sudo make install ------------------------------------------------------------ diff --git a/Makefile.in b/Makefile.in index ec7f14e..265c9ce 100644 --- a/Makefile.in +++ b/Makefile.in @@ -277,6 +277,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -320,6 +321,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ diff --git a/NEWS b/NEWS index ed238d7..d9e8c6f 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ the news section both in the README and the webpage. --> +2016-02-12 babl-0.1.16
+Improvements to half float reference, SIMD, and fast-paths, and CIE float fast +paths; cleanups of fast path extensions. +
2015-11-19 babl-0.1.14
sRGB precision tuning, stability fixes, locale fix for setting error tolerance.
diff --git a/README b/README index 7aa94dc..38920c5 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Babl-0.1.14 +Babl-0.1.16 Contents @@ -59,6 +59,9 @@ babl release. If there are significant improvements to babl when a GEGL release is done a babl release is most often put out just prior to the GEGL release. +2016-02-12 babl-0.1.16 + Improvements to half float reference, SIMD, and fast-paths, and CIE + float fast paths; cleanups of fast path extensions. 2015-11-19 babl-0.1.14 sRGB precision tuning, stability fixes, locale fix for setting error tolerance. @@ -394,6 +397,23 @@ components saturation value +CMYK + +components + + cyan + magenta + yellow + key + +CMY + +components + + cyan + magenta + yellow + CIE Lab components @@ -428,23 +448,6 @@ components CIE H(ab) A -CMYK - -components - - cyan - magenta - yellow - key - -CMY - -components - - cyan - magenta - yellow - HSLA components @@ -1522,19 +1525,6 @@ components u8 Y -B'aG'aR'aA u8 - -bytes/pixel - 4 -model - R'aG'aB'aA -components - - u8 B'a - u8 G'a - u8 R'a - u8 A - cairo-RGB24 bytes/pixel @@ -1598,6 +1588,82 @@ components float saturation float value +B'aG'aR'aA u8 + +bytes/pixel + 4 +model + R'aG'aB'aA +components + + u8 B'a + u8 G'a + u8 R'a + u8 A + +CMYK double + +bytes/pixel + 32 +model + CMYK +components + + double cyan + double magenta + double yellow + double key + +CMY double + +bytes/pixel + 24 +model + CMY +components + + double cyan + double magenta + double yellow + +CMYK float + +bytes/pixel + 16 +model + CMYK +components + + float cyan + float magenta + float yellow + float key + +CMY float + +bytes/pixel + 12 +model + CMY +components + + float cyan + float magenta + float yellow + +CMYK u8 + +bytes/pixel + 4 +model + CMYK +components + + u8 cyan + u8 magenta + u8 yellow + u8 key + CIE Lab double bytes/pixel @@ -1733,69 +1799,6 @@ components float CIE H(ab) float A -CMYK double - -bytes/pixel - 32 -model - CMYK -components - - double cyan - double magenta - double yellow - double key - -CMY double - -bytes/pixel - 24 -model - CMY -components - - double cyan - double magenta - double yellow - -CMYK float - -bytes/pixel - 16 -model - CMYK -components - - float cyan - float magenta - float yellow - float key - -CMY float - -bytes/pixel - 12 -model - CMY -components - - float cyan - float magenta - float yellow - -CMYK u8 - -bytes/pixel - 4 -model - CMYK -components - - u8 cyan - u8 magenta - u8 yellow - u8 key - HSLA double bytes/pixel @@ -1927,21 +1930,21 @@ height of the bar indicates the number of conversions steps needed in a chain of conversions. A DHTML version is also available. - ▂·▃▂·▁ ·· · ·· ▁▂▂▃▃▂ ▂▃▂ ▃ ▃ ▁▁▁▂▂ ▂▁▂▁ ▂ ▂ ▃·· ···· ▁▂ ·· ·· ·· ▃ ── 0 RGBA double + ▂·▃▂·▁▂▁ ▃▂ ·· ·▂ ▂▃ ▃ ·· ▁▂▂▃▃▂▃▂▃▂▃ ▃▃ ▃ ▁▁▁▂▂▂▂▁▂▁▂▃▂▂▃▂▃·· ·· ····▂▁▂ ·· ·· ▃ ── 0 RGBA double ── 1 RGB double ── 2 RaGaBaA double ── 3 R'G'B' double -▂ ▃▂▁▁▂ ▃▃ ▃ ▃▃ ·▁▁▂▂▁ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▂▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▃ ── 4 R'G'B'A double -· ▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃ ▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▃▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ── 5 R'aG'aB'aA double -▁ ▁ ··· ▂▂ ▂ ▂▂ ·▁▁▁···▃▃▂ ▃ ▃ ▁▁·▁▂▁▁▁▂▁ ▂ ▂ ·▂▂ ▂▂▃▂ ▁▂ ▂▂ ▂▂ ▂▂ ▁ ── 6 R'G'B' u8 -▁ ▂▂ ·▁ ▂▂ ▃ ▂▂ ··▁▂▂▁▁▂▃▂ ▃ ▃ ▁▁▁▂▂▁▂▁▂▁ ▂ ▂ ·▂▂ ▂▂▂▂ ▁▂ ▃▃ ▂▃ ▂▂ ▃ ── 7 R'G'B'A u8 -· ▁▁▂ · ▁▁ ▁ ▁▁ ·▁▁▂▂▁ ▁▂▁ ▂▃▂ ···▁▁ ▁·▁· ▁ ▁ ·▁▁ ▁▁▁▁ ·▁ ▁▁ ▁▁ ▁▁ ▃ ── 8 RGBA float -▁ ▂▂▁▂ ▂▂ ▂ ▂▂ ▁▂▂▃▂· ▂▃▂ ▃ ▃ ▁▁·▁▁ ·▁▂▁ ▂ ▂ ·▂▂ ▃▂▂▂ ▁▂ ▂▂ ▂▂ ▂▂ ▃ ── 9 RGB float - ──10 RGB half - ──11 RGBA half +▂ ▃▂▁▁▂▃▂ ▂▁ ▃▃ ▃▃ ▃ ▃▃ ·▁▁▂▂▁▂▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▂▃▂▃ ▃▃ ▃▂▃▃ ▃▃ ▃▃▃▃▃▂▃ ▃▃ ▃▃ ▃ ── 4 R'G'B'A double +· ▃▃▁▂▃▂ ▃ ▁▁ ▁▃ ▃ ▁▁ ▂▃ ▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▂▃▃▃ ▃▃ ▂▂▁▁ ▁▁ ▁▁▁▁▃▂▃ ▁▁ ▁▁ ── 5 R'aG'aB'aA double +▁ ▂ ···▁▁ ▁▂ ▂▂ ▂▂ ▂▃ ▃ ▂▂ ▁▁▁▁···▂▃▂▃ ▃▃ ▃ ▁▁·▁▂▁▁▁▂▁▂▃▂▂▃▂·▂▃ ▃▂ ▂▂▃▂▃▁▂ ▃▂ ▃▂ ▁ ── 6 R'G'B' u8 +▁ ▁▂ ·▁▂▁ ▂▁ ▂▂ ▂▂ ▂▃ ▃ ▂▂ ··▁▂▂▁▁▂▃▂▃ ▃▃ ▃ ▁▁▁▂▂▂▂▁▂▁▂▃▂▂ ▂·▂▂ ▂▂ ▂▂▂▂▂▁▂ ▂▂ ▂▂ ▃ ── 7 R'G'B'A u8 +· ▁▁▂ ·▁· ▂▁ ▁▁ ▁▁ ▁▂ ▂ ▁▁ ·▁▁▂▂▁▂▁▂▁▂▃▂▂▃▂ ···▁▁▁▁·▁·▁▂▁▁▂▁▂▁▁ ▁▁ ▁▁▁▁▁·▁ ▁▁ ▁▁ ▃ ── 8 RGBA float +▁ ▂▃▁▂ ·▁ ▁▂ ▂▂ ▂▂ ▂▃ ▃ ▂▃ ▁▂▁▂▂·▁▂▃▂▃ ▃▃ ▃ ▁▁·▁▁··▁▂▁▂▃▂▂▃▂▂▃▂ ▂▂ ▃▃▂▂·▁▂ ▂▂ ▂▃ ▃ ── 9 RGB float +▂ ▃▃▂▃▁ ▂ ▂▃ ▃▃ ▃▃ ▃ ▃▃ ▂▃▂▃▃▁▂▃ ▃ ▃ ▃ ▂▂▁▂▃▁▁▂▃▂▃ ▃▃ ▃▃▃▃ ▃▃ ▃▃▃▃▁▃▃ ▃▃ ▃▃ ▃ ──10 RGB half +▁ ▂▂▃▂·▁ ▃▂ ▂▂ ▂▂ ▂▃ ▃ ▂▂ ▁▂▂▃▃▂▃▂▃▃▃ ▃▃ ▃ ▁▁▁▂▂▂▂▁▂▁▂▃▂▂▃▂▃▂▂ ▂▂ ▂▂▂▂▂▁▂ ▂▂ ▂▂ ▃ ──11 RGBA half ──12 RaGaBaA half - ──13 R'G'B' half - ──14 R'G'B'A half +▃ ▂ ▁▂▂▁▂▃ ▂ ▁▂▁▂▂·▁ ▃▃▂▃▃▂▂▃ ▃ ▃▂ ▂▃ ▃ ──13 R'G'B' half +▂ ▁▃▂▁▁▂▃▂ ▃▃ ▃▃ ▃ ▃▃ ·▁▁▂▂▁▂▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▂▃▂▃ ▃▃ ▃▂▃▃ ▃▃ ▃▃▃▃▃▂▃ ▃▃ ▃▃ ▃ ──14 R'G'B'A half ──15 R'aG'aB'aA half ──16 RGB u15 ──17 RGBA u15 @@ -1955,18 +1958,18 @@ chain of conversions. A DHTML version is also available. ──25 R'G'B' u32 ──26 R'G'B'A u32 ──27 R'aG'aB'aA u32 -· ▃▁▃▃▁▂ ▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃ ▃ ▃▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──28 Y double -· ▃▁▃▃▁▃ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃ ▃▂ ▃ ▃▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──29 YA double +· ▃▁▂▃▁▂▃▂ ▃ ▁ ▁▃ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▂▃ ▃ ▃ ▂▁▁ ▁▁ ▁▁▁▁▃▂▃ ▁▁ ▁▁ ──28 Y double +· ▃▁▂▃▁▂▃▂ ▃ ▁ ▃ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃ ▃▃ ▃ ▃▂▁▁ ▁▁ ▁▁▁▁▃▂▃ ▁▁ ▁▁ ──29 YA double ──30 YaA double ──31 Y' double ──32 Y'A double -· ▃▁▂▃▁▂ ▁▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▃▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──33 Y'aA double - ──34 YA half +· ▃▁▂▃▁▂▃▂ ▃ ▁▁ ▃ ▃ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▂▃▂▃ ▃▃ ▃▂▁▁ ▁▁ ▁▁▁▁▃▂▃ ▁▁ ▁▁ ──33 Y'aA double +▂ ▃▃▃▃▁▂▃▂ ▃ ▃▃ ▂▂ ▃ ▃▃ ▂▃▃▃▃▃ ▁▂▂▂▃▃▂▃▃ ▂▂▂▃▃▃▃·▁▁▁▂▂▁▂▂▂▃▃ ▃▃ ▃▃▃▃▃▂▁ ▃▃ ▃▃ ──34 YA half ──35 YaA half - ──36 Y half - ──37 Y'A half +▃ ▃▃▂▁▂▃ ▃ ▂ ▃ ▂ ▃ ▃ ▃▂▃▂▂▁▃▃▂▃▃▂ ▃▃▂▃▃▂▂▁▁·▂▂▁▂▂▁▂ ▂▃▂ ▃ ──36 Y half +▃ ▂ ▃▂▂▃ ▃ ▃▂ ▂ ▂ ▁▂▂▃▃▂▃·▁▁▁▃▂▁▃▂ ▃▃▃ ▃▁▂▂▂▃▃▂▃▃▃ ▃▂ ──37 Y'A half ──38 Y'aA half - ──39 Y' half + ▃ ▂▃▃▂▃ ▂▃ ▃ ▂▂ ▂▃▂▃▃▁▂▁▁·▂▂▁▂▂▁ ▃ ▃▃▂▂▁▃▃▂▃▃▂▃ ▃ ▃ ▃ ──39 Y' half ──40 YA u15 ──41 YaA u15 ──42 Y u15 @@ -1979,81 +1982,19 @@ chain of conversions. A DHTML version is also available. ──49 Y'A u32 ──50 Y'aA u32 ──51 Y' u32 -· ▃▁▃▃▁▂ ▁▁ ▁ ▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▃▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──52 Y'CbCr double -· ▃▁▃▃▁▂ ▁▁ ▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▂▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──53 Y'CbCrA double +· ▃▁▃▃▁▂▃▂ ▃ ▁▁ ▁▃ ▃ ▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▃▃▂▃ ▃ ▃▂▁▁ ▁▁ ▁▁▁▁▃▂▃ ▁▁ ▁▁ ──52 Y'CbCr double +· ▃▁▃▃▁▂▃▂ ▃ ▁▁ ▁▃ ▃ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▂▃▂▃ ▃▃ ▂▂▁▁ ▁▁ ▁▁▁▁▃▂▃ ▁▁ ▁▁ ──53 Y'CbCrA double ──54 Y'CbCr u8 -▁ ·▂▁··▁ ▂▂ ▃ ▂▂ ··▁▁· ▂▃▂ ▃ ▃ ▁▁▁▂▂ ▂▁▂▂ ▂ ▂ ▁▂▂ ▂▂▂▂ ▁▂ ▂▂ ▂▂ ▂▂ ▂ ──55 R'G'B'A float -▂ ▁▃▂▁▁▂ ▃▃ ▃ ▃▃ ·▁▁▁▁▃ ▃ ▃ ▃ ▂▂▂▃▃▂▃▂▃▃ ▃ ▃ ▂▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▂ ──56 R'G'B'A u16 -▂ ▁ ▂▁▁▂ ▃▃ ▃ ▃▃ · ··▁ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▂▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▁ ──57 R'aG'aB'aA float -▃ ▂ ▃▂▂▃ ▃▃ ▃ ▃▃ ▁▂ ·▂▂▃ ▃ ▃ ▃ ▃▃▃▃▃▃▃▃▃▃ ▃ ▃ ▃▃▃ ▃▃▃▃ ▃▃ ▃▃ ▃▃ ▃▃ ▁ ──58 R'aG'aB'aA u16 -▃ ▂ ▂▃ ▁▂· ▂▂ ▃▃▃ ▃▃▃▃ ▃ ▃ ▃ · ──59 R'aG'aB'aA u8 -▂ ▃▃·▁▁· ▃▃ ▃ ▃▃ ▂▃▃▃ ▃ ▃ ▃ ▃ ▂▂▁▂▂ ▁▂▃▂ ▃ ▃ ▁▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▂ ──60 R'G'B' float -▃ ·▁▂▁ ▃ ▃ ▁ ▃▃▃▃▃▃▂▃ ▃ ▃ ▁ ▃ ▂ ──61 R'G'B' u16 -▂ ▁▃▂▁▁▂ ▃▃ ▃ ▃▃ ·▁▁▂▂▁ ·· ▂ ·▁▁ ▂▂▂▃▃ ▃·▁▁ ▁ ▂ ▂▃▃ ▃▃▃▃ ▂▁ ▃▃ ▃▃ ▃▃ ▃ ──62 Y'A float -▃ ▂ ▃▂▂▃ ▁▂·▁▁▂ ▁ ▁ ▁·▂ ▃▃▃ ▃▁▂▂ ▂ ▃ ▃ ▃▂ ▂ ──63 Y'aA float -▃ ▂ ▁▂▂▁ ▁▂▁▂▂· · ▁ · ▃▃▂▃▃ ▂▁▁· ▂ ▁ ▂ ▃▂ ▃ ──64 Y' float -▃ ▂ ▃▃▂▃ ▃ ▁▂▂▃▃▂▂·▂ ▃ ·▃▃ ▃▃▃ ▃▃▃▁▂▂ ▂ ▃ ▃ ▃▂ ▃ ──65 Y'A u16 - ▃ ▃ ▂▃▁▂▂▃ ▁·▂ ▂▁▃ ▃ ▃ ▃ ──66 Y'aA u16 - ▃ ▃▃▃▂ ▂▃▂▃▃▁▃▁▁· ▃▃· ▃ ▃▂▂▁ ▃ ▂ ▃ ▃ ▂ ──67 Y' u16 -▁ ▂▃▃▂·▂ ▂▂ ▂ ▂▂ ▁▃▂▃▃▂▂·▁▁·▃ ▂▂ ▁▁▂▂▂▁▂·▁▁ ▁ ▂ ▃▂▂ ▂▃▂▂ ▁▁ ▃▃ ▃▂ ▂▂ ▃ ──68 Y'A u8 - ▃ ▃ ▂▃▁▂▂▃ ▁·▂ · ▃▃▃ ▃ ▃ ──69 Y'aA u8 -▁ ▃▂▂▃·▁ ▂▂ ▂ ▂▂ ▂▃▂▃▃▁▃▁▁·▃▃·▂ ▁▁▂▃▂▁▂▁▁· ▂ ▁ ▃▂▂ ▂▂▂▂ ▃▂ ▂▂ ▂▂ ▂▂ ▃ ──70 Y' u8 -▃ ▁▂▂▁ ▃ ▃ ▂· ▃▃▂▃▃ ▂▃ ▃ ▃ ▂ ▃ ▃ ──71 Y'CbCr float -▂ ▁▃▂▁▁▂ ▃▃ ▃ ▃ ·▁▁▂▂▁ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▃▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▃ ──72 Y'CbCrA float -▁ ▂▂▃▂·▁ ▂▂ ▂ ▂▂ ▁▂▂▃▂▂▂▂▃▂ ▃ ▃ ··▂▁▁▂▁▂▁ ▂ ▂ ▃▂▂ ▂▂▂▂ ▂▂ ▂▃ ▃▂ ▂▂ ▃ ──73 RGBA u16 -▁ ▂▂▂▂·▁ ▂▂ ▂ ▃▃ ▁▂▂▃▃▂▂▂▃▂ ▃ ▃ ·▂▁▁·▁▂▁ ▂ ▂ ▂▂▃ ▂▂▂▂ ▁▂ ▃▂ ▂▂ ▂▂ ▃ ──74 RGBA u8 -▁ ▂▂▃▂·▁ ▂▂ ▂ ▂▂ ▁▂▂▃▃▂ ▂▃▂ ▃ ▃ ▁ ·· ▂▁▂▁ ▂ ▂ ▃▂▂ ▂▂▂▂ ▁▂ ▂▂ ▂▂ ▂▂ ▃ ──75 RaGaBaA float -▂ ▃▃▂▃▁▂ ▃▃ ▃ ▃▃ ▂▃▃▃▃▃▃▃ ▃ ▃ ▃ ▂▂ ·▂▃▂▃▂ ▃ ▃ ▂▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▃ ──76 RaGaBaA u16 -▂ ▃▃▂▃▁▂ ▃▃ ▃ ▃▃ ▂▃▃▂▃▃▃▃ ▃ ▃ ▃ ▂ · ▂ ▂▃▂ ▃ ▃ ▂▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▃ ──77 RaGaBaA u8 -▂ ▃▃▂▃▁· ▃▃ ▃ ▃▃ ▂▃▃▃▃▁▃▃ ▃ ▃ ▃ ▂▁▁▂ ·▂▃▃ ▃ ▃ ▃▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ▃ ──78 RGB u16 -▁ ▂▂▁▂·· ▂▂ ▂ ▃▂ ▁▂▂▃▂▁▃▃▃▂ ▃ ▃ ▁··▁· ▁▂▁ ▂ ▂ ▂▂▂ ▂▂▃▂ ▂▂ ▂▂ ▂▂ ▂▂ ▃ ──79 RGB u8 -▁ ▂▂▃▂·▁ ▂ ▂ ▂▂ ▁▂▂▃▃▂ ·▁▁ ▃ ▁▃▂ ▁▁▁▂▂ ·· · ▁ ▃▂▂ ▂▂▂▂ ▁· ▂▂ ▂▂ ▂▂ ▃ ──80 YA float -▂ ▃▃▂▃▁▂ ▃▃ ▃ ▃▃ ▂▃▃▃▃▃ ▃▃▃ ▂▃▃ ▂▂·▁▁ ▃ ▂ ▁ ▂ ▃▃▃ ▃▃▃▃ ▂▃ ▃▃ ▃▃ ▃▃ ──81 YaA float -▂ ▃▃▂▃▁· ▃ ▃ ▃▃ ▂▃▂▃▃▁ ▁▁· ▂▃▁ ▂▂▁▂▂ ▁· ▁ · ▃▃▃ ▃▃▃▃ ▂▁ ▃▃ ▃▃ ▃▃ ▃ ──82 Y float -▂ ▃▃ ▃▁▂ ▃ ▃ ▃▃ ▂▃▃▃▃▃▃▁▃▂ ▂▃▃ ▂▂▂▃▃▂▃·▁ · ▃ ▃▃ ▃▃▃▃ ▂▁ ▃ ▃▃ ▃▃ ──83 YA u16 -▃ ▃ ▂▃ ▃ ▃▃▃ ▂▃▃ ▃▃▁▂▂▃▃▃·▃ ▃ ▃ ▃▂ ──84 YaA u16 -▃ ▃ ▂▁ ▃ ▃ ▂ ▂▃▁ ▃ ▂ ▃▂▂▃▃▃▃▁▁· ▃ · ▃▂ ──85 Y u16 -▁ ▃▃▃▃·▂ ▂▂ ▂ ▂▃ ▂▃▃▃▃▃▃▁▂▂ ▂▃▃ ▂▁▁▂▂▃▃·▁▁· ▂ ▃▃▃ ▃▃▂▃ ▂▁ ▃▂ ▃▂ ▂▃ ▃ ──86 YA u8 -▃ ▃ ▂▃ ▃ ▃▃▃ ▂▃▃ ▃ ▁▂▂▃ ▁·▂ · ▃ ▃▂ ──87 YaA u8 -▁ ▂▂▃▃·▁ ▂▂ ▂ ▂▂ ▃▂▃▃▃▂▂▂▂▁ ▃ ▁ ▁▁▂▃▂▃▂▁▁·▃ ·▂ ▂▂▂ ▂▂▂▂ ▃▂ ▂▂ ▂▂ ▂▂ ▃ ──88 Y u8 - ──89 B'aG'aR'aA u8 - ──90 cairo-RGB24 -· ▃▁▂▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──91 HSVA double -· ▃▁▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▃▃▂ ▃ ▃ ▃ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──92 HSV double - ──93 HSVA float - ──94 HSV float -· ▃▁▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▃ ▃ ▃ ▃▁▁ ▁▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──95 CIE Lab double -· ▃▁▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▂▁▁ ▁▁ ▁▁ ▁▁ ▁▁ ──96 CIE Lab alpha double -· ▃▁▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▃▃▂ ▃ ▃ ▂▁▁ ▁ ▁ ▂▃ ▁▁ ▁▁ ▁▁ ──97 CIE LCH(ab) double -· ▃▁▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▂▁▁ ▁▁ ▂▃ ▁▁ ▁▁ ▁▁ ──98 CIE LCH(ab) alpha double - ──99 CIE Lab float -▁ ▂▂▃▂·▁ ▂▂ ▂ ▂▂ ▁▂▂▃▃▂ ▂▃▂ ▃ ▃ ▁▁▁▂▂ ▂▁▂▁ ▂ ▂ ▁▂▂ ▂ ▂▂ ▂▂ ▂▂ ▂▂ ▃ ──100 CIE Lab alpha float - ──101 CIE L alpha float - ──102 CIE Lab u8 - ──103 CIE Lab u16 - ──104 CIE LCH(ab) float - ──105 CIE LCH(ab) alpha float -· ▃▁▂▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▂▁▁ ▁▁▁▁ ▂▃ ▁ ▁▁ ▁▁ ──106 CMYK double -· ▃▁▂▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▃ ▃ ▂ ▃▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ──107 CMY double - ──108 CMYK float - ──109 CMY float - ──110 CMYK u8 -· ▃▁▂▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▃▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁ ▁▁ ──111 HSLA double -· ▃▁▂▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▃▃▃ ▃ ▂ ▂▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ──112 HSL double - ──113 HSLA float - ──114 HSL float -· ▃▁▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▃ ▃ ▃ ▂▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ▁ ──115 Y'CbCr709 double -· ▃▁▃▃▁▂ ▁▁ ▁ ▁▁ ▂▃▃▃▃▃ ▃ ▃ ▃ ▃ ▂▂▂▃▃ ▃▂▃▂ ▃ ▃ ▂▁▁ ▁▁▁▁ ▂▃ ▁▁ ▁▁ ──116 Y'CbCrA709 double - ──117 Y'CbCrA709 float - ──118 Y'CbCr709 float - ──119 cairo-ARGB32 - ──120 cairo-A8 -||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||111111111111111111111 -||||||||||111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112 -0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -total length: 7788 -total cost : 20663828 +▁ ·▂▁··▁▂▁ ▁· ▂▂ ▃▂ ▂▃ ▃ ▂▂ ··▁▁·▁▂▃▂▃ ▃▃ ▃ ▁▁▁▂▂▂▂▁▂▁▂▃▂▂▃▃▁▂▂ ▂▂ ▂▂▂▂▂▁▂ ▂▂ ▂▂ ▂ ──55 R'G'B'A float +▂ ▁▃▂·▁▂▃▂ ▂▁ ▃▃ ▃▃ ▃ ▃▃ ·▁▁▁▁▃ ▃ ▃ ▃ ▂▂▃▃▃▂▃▂▃▂▃ ▃▃ ▃▂▃▃ ▃▃ ▃▃▃▃▃▂▃ ▃▃ ▃▃ ▂ ──56 R'G'B'A u16 +▂ ▁ ▂▁▁▂▃▂ ▂▁ ▃▃ ▃▃ ▃ ▃▃ · ··▁▂▃ ▃ ▃ ▃ ▂▂▂▃▃▃▃▂▃▃▃ ▃▃ ▃▂▃▃ ▃▃ ▃▃▃▃▃▂▃ ▃▃ ▃▃ ▁ ──57 R'aG'aB'aA float +▃ ▂ ▃▂▂▃▃▃ ▃▂ ▃▃ ▃▃ ▃ ▃▃ ▁▂ ·▂▃▃ ▃ ▃ ▃ ▃▃▃▃▃▃▃▃▃▃▃ ▃▃ ▃▃▃▃ ▃▃ ▃▃▃▃▃▃▃ ▃▃ ▃▃ ▁ ──58 R'aG'aB'aA u16 +▃ ▂ ▂▃ ▃ ▃▂ ▁▂· ▂▂ ▃▃▃ ▃▃▃▃ ▃ ▃ ▃ · ──59 R'aG'aB'aA u8 +▂ ▁▃·▁▁·▁▂ ·▁ ▃▃ ▃▃ ▃ ▃▃ ·▁·▁ ·▃ ▃ ▃ ▃ ▂▂▁▃▂▁▁▂▃▂▃ ▃▃ ▃▁▃▃ ▃▃ ▃▃▃▃▁▂▃ ▃▃ ▃▃ ▂ ──60 R'G'B' float +▃ ▂ ·▁▂▁▂▃ ▁▂ ▁▂▁▂▁ ▃▃▂▃▃▂▂▃ ▃ ▃▁ ▂▃ ▂ ──61 R'G'B' u16 +▂ ▁▃▂▁▁▂▃▂ ▂▁ ▃▃ ▃▁ ▂· ▁ ▃▃ ·▁▁▂▂▁ ···▁▁·▁▁ ▂▂▂▃▃▃▃·▁▁▁▂▂▁▂▂▃▃▃ ▃▃ ▃▃▃▃▃▂▁ ▃▃ ▃▃ ▃ ──62 Y'A float +▃ ▂ ▃▂▂▃ ▃ ▃▂ ▂ ▃▁ ▂ ▁▂·▁▁▂▃ ▁▁▁▂▁·▂ ▃▃▃ ▃▁▂▂▂▃▃▂▃▃▃ ▃▂ ▂ ──63 Y'aA float +▃ ▂ ▁▂▂▁▂▃ ▁▂ ▂ ▁▁ · ▁▂▁▂▂·▁· ▁▁·▁▁· ▃▃▂▃▃▂▂▁▁·▂▂▁▂▂▁▂ ▂▃▂ ▃ ──6 Environment @@ -2188,4 +2129,4 @@ Jon Nordby Massimo Valentini stability fixes -/babl-0.1.14 +/babl-0.1.16 diff --git a/babl/Makefile.in b/babl/Makefile.in index e5a4de4..ba7305d 100644 --- a/babl/Makefile.in +++ b/babl/Makefile.in @@ -302,6 +302,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -345,6 +346,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ diff --git a/babl/babl-cpuaccel.c b/babl/babl-cpuaccel.c index 3445cf6..59fdcdd 100644 --- a/babl/babl-cpuaccel.c +++ b/babl/babl-cpuaccel.c @@ -114,7 +114,12 @@ enum enum { - ARCH_X86_INTEL_FEATURE_PNI = 1 << 0 + ARCH_X86_INTEL_FEATURE_PNI = 1 << 0, + ARCH_X86_INTEL_FEATURE_SSSE3 = 1 << 9, + ARCH_X86_INTEL_FEATURE_SSE4_1 = 1 << 19, + ARCH_X86_INTEL_FEATURE_SSE4_2 = 1 << 20, + ARCH_X86_INTEL_FEATURE_AVX = 1 << 28, + ARCH_X86_INTEL_FEATURE_F16C = 1 << 29, }; #if !defined(ARCH_X86_64) && (defined(PIC) || defined(__PIC__)) @@ -234,6 +239,15 @@ arch_accel_intel (void) if (ecx & ARCH_X86_INTEL_FEATURE_PNI) caps |= BABL_CPU_ACCEL_X86_SSE3; + + if (ecx & ARCH_X86_INTEL_FEATURE_SSSE3) + caps |= BABL_CPU_ACCEL_X86_SSSE3; + + if (ecx & ARCH_X86_INTEL_FEATURE_SSE4_1) + caps |= BABL_CPU_ACCEL_X86_SSE4_1; + + if (ecx & ARCH_X86_INTEL_FEATURE_F16C) + caps |= BABL_CPU_ACCEL_X86_F16C; #endif /* USE_SSE */ } #endif /* USE_MMX */ @@ -399,7 +413,11 @@ arch_accel (void) #ifdef USE_SSE if ((caps & BABL_CPU_ACCEL_X86_SSE) && !arch_accel_sse_os_support ()) - caps &= ~(BABL_CPU_ACCEL_X86_SSE | BABL_CPU_ACCEL_X86_SSE2); + caps &= ~(BABL_CPU_ACCEL_X86_SSE | + BABL_CPU_ACCEL_X86_SSE2 | + BABL_CPU_ACCEL_X86_SSE3 | + BABL_CPU_ACCEL_X86_SSSE3 | + BABL_CPU_ACCEL_X86_SSE4_1); #endif return caps; diff --git a/babl/babl-cpuaccel.h b/babl/babl-cpuaccel.h index e701e2a..8040d73 100644 --- a/babl/babl-cpuaccel.h +++ b/babl/babl-cpuaccel.h @@ -30,6 +30,11 @@ typedef enum BABL_CPU_ACCEL_X86_SSE = 0x10000000, BABL_CPU_ACCEL_X86_SSE2 = 0x08000000, BABL_CPU_ACCEL_X86_SSE3 = 0x02000000, + BABL_CPU_ACCEL_X86_SSSE3 = 0x00800000, + BABL_CPU_ACCEL_X86_SSE4_1 = 0x00400000, + /* BABL_CPU_ACCEL_X86_SSE4_2 = 0x00200000, */ + /* BABL_CPU_ACCEL_X86_AVX = 0x00080000, */ + BABL_CPU_ACCEL_X86_F16C = 0x00040000, /* powerpc accelerations */ BABL_CPU_ACCEL_PPC_ALTIVEC = 0x04000000, diff --git a/babl/babl-version.h b/babl/babl-version.h index 6188565..172d6fe 100644 --- a/babl/babl-version.h +++ b/babl/babl-version.h @@ -34,7 +34,7 @@ #define BABL_MAJOR_VERSION 0 #define BABL_MINOR_VERSION 1 -#define BABL_MICRO_VERSION 14 +#define BABL_MICRO_VERSION 16 /** Get the version information on the babl library */ void babl_get_version (int *major, diff --git a/babl/base/Makefile.in b/babl/base/Makefile.in index 95ded47..b1b2453 100644 --- a/babl/base/Makefile.in +++ b/babl/base/Makefile.in @@ -216,6 +216,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -259,6 +260,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ diff --git a/babl/base/type-half.c b/babl/base/type-half.c index e45e34a..61a63ca 100644 --- a/babl/base/type-half.c +++ b/babl/base/type-half.c @@ -129,114 +129,6 @@ static void doubles2halfp(void *target, void *source, long numel) } } -#if 0 -//----------------------------------------------------------------------------- - -static void halfp2singles(void *target, void *source, long numel) -{ - uint16_t *hp = (uint16_t *) source; // Type pun input as an unsigned 16-bit int - uint32_t *xp = (uint32_t *) target; // Type pun output as an unsigned 32-bit int - uint16_t h, hs, he, hm; - uint32_t xs, xe, xm; - int32_t xes; - int e; - - if( source == NULL || target == NULL ) // Nothing to convert (e.g., imag part of pure real) - return; - while( numel-- ) { - h = *hp++; - if( (h & 0x7FFFu) == 0 ) { // Signed zero - *xp++ = ((uint32_t) h) << 16; // Return the signed zero - } else { // Not zero - hs = h & 0x8000u; // Pick off sign bit - he = h & 0x7C00u; // Pick off exponent bits - hm = h & 0x03FFu; // Pick off mantissa bits - if( he == 0 ) { // Denormal will convert to normalized - e = -1; // The following loop figures out how much extra to adjust the exponent - do { - e++; - hm <<= 1; - } while( (hm & 0x0400u) == 0 ); // Shift until leading bit overflows into exponent bit - xs = ((uint32_t) hs) << 16; // Sign bit - xes = ((int32_t) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single - xe = (uint32_t) (xes << 23); // Exponent - xm = ((uint32_t) (hm & 0x03FFu)) << 13; // Mantissa - *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits - } else if( he == 0x7C00u ) { // Inf or NaN (all the exponent bits are set) - if( hm == 0 ) { // If mantissa is zero ... - *xp++ = (((uint32_t) hs) << 16) | ((uint32_t) 0x7F800000u); // Signed Inf - } else { - *xp++ = (uint32_t) 0xFFC00000u; // NaN, only 1st mantissa bit set - } - } else { // Normalized number - xs = ((uint32_t) hs) << 16; // Sign bit - xes = ((int32_t) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single - xe = (uint32_t) (xes << 23); // Exponent - xm = ((uint32_t) hm) << 13; // Mantissa - *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits - } - } - } -} - -static void singles2halfp(void *target, void *source, long numel) -{ - uint16_t *hp = (uint16_t *) target; // Type pun output as an unsigned 16-bit int - uint32_t *xp = (uint32_t *) source; // Type pun input as an unsigned 32-bit int - uint16_t hs, he, hm; - uint32_t x, xs, xe, xm; - int hes; - - if( source == NULL || target == NULL ) { // Nothing to convert (e.g., imag part of pure real) - return; - } - while( numel-- ) { - x = *xp++; - if( (x & 0x7FFFFFFFu) == 0 ) { // Signed zero - *hp++ = (uint16_t) (x >> 16); // Return the signed zero - } else { // Not zero - xs = x & 0x80000000u; // Pick off sign bit - xe = x & 0x7F800000u; // Pick off exponent bits - xm = x & 0x007FFFFFu; // Pick off mantissa bits - if( xe == 0 ) { // Denormal will underflow, return a signed zero - *hp++ = (uint16_t) (xs >> 16); - } else if( xe == 0x7F800000u ) { // Inf or NaN (all the exponent bits are set) - if( xm == 0 ) { // If mantissa is zero ... - *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf - } else { - *hp++ = (uint16_t) 0xFE00u; // NaN, only 1st mantissa bit set - } - } else { // Normalized number - hs = (uint16_t) (xs >> 16); // Sign bit - hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp - if( hes >= 0x1F ) { // Overflow - *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf - } else if( hes <= 0 ) { // Underflow - if( (14 - hes) > 24 ) { // Mantissa shifted all the way off & no rounding possibility - hm = (uint16_t) 0u; // Set mantissa to zero - } else { - xm |= 0x00800000u; // Add the hidden leading bit - hm = (uint16_t) (xm >> (14 - hes)); // Mantissa - if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding - hm += (uint16_t) 1u; // Round, might overflow into exp bit, but this is OK - } - *hp++ = (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero - } else { - he = (uint16_t) (hes << 10); // Exponent - hm = (uint16_t) (xm >> 13); // Mantissa - if( xm & 0x00001000u ) // Check for rounding - *hp++ = (hs | he | hm) + (uint16_t) 1u; // Round, might overflow to inf, this is OK - else - *hp++ = (hs | he | hm); // No rounding - } - } - } - } -} -#endif - -//----------------------------------------------------------------------------- - static void halfp2doubles(void *target, void *source, long numel) { uint16_t *hp = (uint16_t *) source; // Type pun input as an unsigned 16-bit int @@ -245,15 +137,15 @@ static void halfp2doubles(void *target, void *source, long numel) uint32_t xs, xe, xm; int32_t xes; int e; - - xp += next; // Little Endian adjustment if necessary if( source == NULL || target == NULL ) // Nothing to convert (e.g., imag part of pure real) return; while( numel-- ) { + uint32_t x; + h = *hp++; if( (h & 0x7FFFu) == 0 ) { // Signed zero - *xp++ = ((uint32_t) h) << 16; // Return the signed zero + x = ((uint32_t) h) << 16; // Return the signed zero } else { // Not zero hs = h & 0x8000u; // Pick off sign bit he = h & 0x7C00u; // Pick off exponent bits @@ -268,22 +160,26 @@ static void halfp2doubles(void *target, void *source, long numel) xes = ((int32_t) (he >> 10)) - 15 + 1023 - e; // Exponent unbias the halfp, then bias the double xe = (uint32_t) (xes << 20); // Exponent xm = ((uint32_t) (hm & 0x03FFu)) << 10; // Mantissa - *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits + x = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits } else if( he == 0x7C00u ) { // Inf or NaN (all the exponent bits are set) if( hm == 0 ) { // If mantissa is zero ... - *xp++ = (((uint32_t) hs) << 16) | ((uint32_t) 0x7FF00000u); // Signed Inf + x = (((uint32_t) hs) << 16) | ((uint32_t) 0x7FF00000u); // Signed Inf } else { - *xp++ = (uint32_t) 0xFFF80000u; // NaN, only the 1st mantissa bit set + x = (uint32_t) 0xFFF80000u; // NaN, only the 1st mantissa bit set } } else { xs = ((uint32_t) hs) << 16; // Sign bit xes = ((int32_t) (he >> 10)) - 15 + 1023; // Exponent unbias the halfp, then bias the double xe = (uint32_t) (xes << 20); // Exponent xm = ((uint32_t) hm) << 10; // Mantissa - *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits + x = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits } } - xp++; // Skip over the remaining 32 bits of the mantissa + + xp[1 - next] = 0; + xp[next] = x; + + xp += 2; } } diff --git a/config.h.in b/config.h.in index 159ef0a..4ba3e33 100644 --- a/config.h.in +++ b/config.h.in @@ -109,6 +109,9 @@ /* Define to 1 if AltiVec support is available. */ #undef USE_ALTIVEC +/* Define to 1 if f16c intrinsics are available. */ +#undef USE_F16C + /* Define to 1 if MMX assembly is available. */ #undef USE_MMX @@ -117,3 +120,6 @@ /* Define to 1 if SSE2 assembly is available. */ #undef USE_SSE2 + +/* Define to 1 if SSE4_1 assembly is available. */ +#undef USE_SSE4_1 diff --git a/configure b/configure index dc0c339..2cc2fd9 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for babl 0.1.14. +# Generated by GNU Autoconf 2.69 for babl 0.1.16. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='babl' PACKAGE_TARNAME='babl' -PACKAGE_VERSION='0.1.14' -PACKAGE_STRING='babl 0.1.14' +PACKAGE_VERSION='0.1.16' +PACKAGE_STRING='babl 0.1.16' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -636,6 +636,8 @@ LIBOBJS HAVE_SRANDOM_FALSE HAVE_SRANDOM_TRUE ALTIVEC_EXTRA_CFLAGS +F16C_EXTRA_CFLAGS +SSE4_1_EXTRA_CFLAGS SSE2_EXTRA_CFLAGS SSE_EXTRA_CFLAGS MMX_EXTRA_CFLAGS @@ -812,6 +814,8 @@ enable_docs enable_mmx enable_sse enable_sse2 +enable_sse4_1 +enable_f16c enable_altivec ' ac_precious_vars='build_alias @@ -1373,7 +1377,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures babl 0.1.14 to adapt to many kinds of systems. +\`configure' configures babl 0.1.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1445,7 +1449,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of babl 0.1.14:";; + short | recursive ) echo "Configuration of babl 0.1.16:";; esac cat <<\_ACEOF @@ -1471,6 +1475,8 @@ Optional Features: --enable-mmx enable MMX support (default=auto) --enable-sse enable SSE support (default=auto) --enable-sse2 enable SSE2 support (default=auto) + --enable-sse4_1 enable SSE4_1 support (default=auto) + --enable-f16c enable hardware half-float support (default=auto) --enable-altivec enable AltiVec support (default=auto) Optional Packages: @@ -1558,7 +1564,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -babl configure 0.1.14 +babl configure 0.1.16 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1923,7 +1929,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by babl $as_me 0.1.14, which was +It was created by babl $as_me 0.1.16, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2279,11 +2285,11 @@ ac_config_headers="$ac_config_headers config.h" BABL_MAJOR_VERSION=0 BABL_MINOR_VERSION=1 -BABL_MICRO_VERSION=14 +BABL_MICRO_VERSION=16 BABL_INTERFACE_AGE=1 -BABL_BINARY_AGE=114 -BABL_VERSION=0.1.14 -BABL_REAL_VERSION=0.1.14 +BABL_BINARY_AGE=116 +BABL_VERSION=0.1.16 +BABL_REAL_VERSION=0.1.16 BABL_API_VERSION=0.1 @@ -2318,7 +2324,7 @@ fi -BABL_LIBRARY_VERSION="113:1:113" +BABL_LIBRARY_VERSION="115:1:115" BABL_CURRENT_MINUS_AGE=0 @@ -2950,7 +2956,7 @@ fi # Define the identity of the package. PACKAGE='babl' - VERSION='0.1.14' + VERSION='0.1.16' # Some tools Automake needs. @@ -12961,6 +12967,22 @@ else fi +# Check whether --enable-sse4_1 was given. +if test "${enable_sse4_1+set}" = set; then : + enableval=$enable_sse4_1; +else + enable_sse4_1=$enable_sse +fi + + +# Check whether --enable-f16c was given. +if test "${enable_f16c+set}" = set; then : + enableval=$enable_f16c; +else + enable_f16c=$enable_sse +fi + + if test "x$enable_mmx" = xyes; then MMX_EXTRA_CFLAGS= @@ -12998,6 +13020,7 @@ $as_echo "$MMX_EXTRA_CFLAGS_works" >&6; } SSE_EXTRA_CFLAGS= SSE2_EXTRA_CFLAGS= + SSE4_1_EXTRA_CFLAGS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile MMX code" >&5 $as_echo_n "checking whether we can compile MMX code... " >&6; } @@ -13232,6 +13255,150 @@ $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The assembler does not support the SSE2 command set." >&5 $as_echo "$as_me: WARNING: The assembler does not support the SSE2 command set." >&2;} +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + if test "x$enable_sse4_1" = xyes; then + + sse4_1_flag= + for flag in '-msse4.1'; do + if test -z "$sse4_1_flag"; then + sse4_1_flag_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $flag" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands $flag" >&5 +$as_echo_n "checking whether $CC understands $flag... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + sse4_1_flag_works=yes +else + sse4_1_flag_works=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sse4_1_flag_works" >&5 +$as_echo "$sse4_1_flag_works" >&6; } + CFLAGS="$sse4_1_flag_save_CFLAGS" + if test "x$sse4_1_flag_works" = "xyes"; then + sse4_1_flag="$flag" + fi + fi + done + + SSE4_1_EXTRA_CFLAGS="$SSE_EXTRA_CFLAGS $sse4_1_flag" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile SSE4_1 code" >&5 +$as_echo_n "checking whether we can compile SSE4_1 code... " >&6; } + + CFLAGS="$CFLAGS $sse4_1_flag" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +asm ("pmovzxbd %xmm0,%xmm1"); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define USE_SSE4_1 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + enable_sse4_1=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The assembler does not support the SSE4_1 command set." >&5 +$as_echo "$as_me: WARNING: The assembler does not support the SSE4_1 command set." >&2;} + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + fi + + CFLAGS="$mmx_save_CFLAGS" + + if test "x$enable_f16c" = xyes; then + + f16c_flag= + for flag in '-mf16c'; do + if test -z "$f16c_flag"; then + f16c_flag_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $flag" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands $flag" >&5 +$as_echo_n "checking whether $CC understands $flag... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + f16c_flag_works=yes +else + f16c_flag_works=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $f16c_flag_works" >&5 +$as_echo "$f16c_flag_works" >&6; } + CFLAGS="$f16c_flag_save_CFLAGS" + if test "x$f16c_flag_works" = "xyes"; then + f16c_flag="$flag" + fi + fi + done + + F16C_EXTRA_CFLAGS="$SSE_EXTRA_CFLAGS $f16c_flag" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile half-floating point code" >&5 +$as_echo_n "checking whether we can compile half-floating point code... " >&6; } + + CFLAGS="$CFLAGS $sse_flag $f16c_flag" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +__m128 val = _mm_cvtph_ps ((__m128i)_mm_setzero_ps()); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define USE_F16C 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + enable_f16c=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The compiler does not support f16c intrinsics." >&5 +$as_echo "$as_me: WARNING: The compiler does not support f16c intrinsics." >&2;} + fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi @@ -13253,6 +13420,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + fi @@ -14155,7 +14324,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by babl $as_me 0.1.14, which was +This file was extended by babl $as_me 0.1.16, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14221,7 +14390,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -babl config.status 0.1.14 +babl config.status 0.1.16 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 53803f5..30b88d1 100644 --- a/configure.ac +++ b/configure.ac @@ -14,7 +14,7 @@ AC_PREREQ(2.54) m4_define([babl_major_version], [0]) m4_define([babl_minor_version], [1]) -m4_define([babl_micro_version], [14]) +m4_define([babl_micro_version], [16]) m4_define([babl_real_version], [babl_major_version.babl_minor_version.babl_micro_version]) m4_define([babl_version], [babl_real_version]) @@ -299,10 +299,19 @@ AC_ARG_ENABLE(sse2, [ --enable-sse2 enable SSE2 support (default=auto)],, enable_sse2=$enable_sse) +AC_ARG_ENABLE(sse4_1, + [ --enable-sse4_1 enable SSE4_1 support (default=auto)],, + enable_sse4_1=$enable_sse) + +AC_ARG_ENABLE(f16c, + [ --enable-f16c enable hardware half-float support (default=auto)],, + enable_f16c=$enable_sse) + if test "x$enable_mmx" = xyes; then BABL_DETECT_CFLAGS(MMX_EXTRA_CFLAGS, '-mmmx') SSE_EXTRA_CFLAGS= SSE2_EXTRA_CFLAGS= + SSE4_1_EXTRA_CFLAGS= AC_MSG_CHECKING(whether we can compile MMX code) @@ -353,6 +362,44 @@ if test "x$enable_mmx" = xyes; then AC_MSG_RESULT(no) AC_MSG_WARN([The assembler does not support the SSE2 command set.]) ) + + if test "x$enable_sse4_1" = xyes; then + BABL_DETECT_CFLAGS(sse4_1_flag, '-msse4.1') + SSE4_1_EXTRA_CFLAGS="$SSE_EXTRA_CFLAGS $sse4_1_flag" + + AC_MSG_CHECKING(whether we can compile SSE4_1 code) + + CFLAGS="$CFLAGS $sse4_1_flag" + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[asm ("pmovzxbd %xmm0,%xmm1");])], + AC_DEFINE(USE_SSE4_1, 1, [Define to 1 if SSE4_1 assembly is available.]) + AC_MSG_RESULT(yes) + , + enable_sse4_1=no + AC_MSG_RESULT(no) + AC_MSG_WARN([The assembler does not support the SSE4_1 command set.]) + ) + fi + fi + + CFLAGS="$mmx_save_CFLAGS" + + if test "x$enable_f16c" = xyes; then + BABL_DETECT_CFLAGS(f16c_flag, '-mf16c') + F16C_EXTRA_CFLAGS="$SSE_EXTRA_CFLAGS $f16c_flag" + + AC_MSG_CHECKING(whether we can compile half-floating point code) + + CFLAGS="$CFLAGS $sse_flag $f16c_flag" + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ],[__m128 val = _mm_cvtph_ps ((__m128i)_mm_setzero_ps());])], + AC_DEFINE(USE_F16C, 1, [Define to 1 if f16c intrinsics are available.]) + AC_MSG_RESULT(yes) + , + enable_f16c=no + AC_MSG_RESULT(no) + AC_MSG_WARN([The compiler does not support f16c intrinsics.]) + ) fi fi @@ -367,6 +414,8 @@ if test "x$enable_mmx" = xyes; then AC_SUBST(MMX_EXTRA_CFLAGS) AC_SUBST(SSE_EXTRA_CFLAGS) AC_SUBST(SSE2_EXTRA_CFLAGS) + AC_SUBST(SSE4_1_EXTRA_CFLAGS) + AC_SUBST(F16C_EXTRA_CFLAGS) fi diff --git a/docs/Makefile.in b/docs/Makefile.in index eddff64..e991f4f 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -222,6 +222,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -265,6 +266,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ diff --git a/docs/graphics/Makefile.in b/docs/graphics/Makefile.in index 492f77d..cff8d7c 100644 --- a/docs/graphics/Makefile.in +++ b/docs/graphics/Makefile.in @@ -162,6 +162,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -205,6 +206,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ diff --git a/docs/graphics/babl-16x16.png b/docs/graphics/babl-16x16.png index aea6726cedd077078db077698a41f224fabb7c54..57ad178affd0a31a67e5f99115c15214199d729c 100644 GIT binary patch delta 464 zcmV;>0Wbdf1N;M!Hh-~6L_t(IjqQ?8OH^STg`fL--}_$2asHT#2n11M(6L3(Mi)v% z;i|9DqG%v!5fStOTJ!-TaizElS_QUF*CV&044f7+DwCAMFr&<$*Z0o7Eh3_JxoOh_ zXL%0iz=3~_I)g{J$Zc|5p~+kQSJvy~IN>ENE)!D#_$^@k-hcRfI+b2b4W>rbfI6p) z`WmTdKk}ki;luDF0ju=5ieZHvS^!?HR=a=Hs6X2LyfHL0c4=f|=MClkGG@S#=!8fj zoH*KX`_p!Ld%Anj?Q_gsLe>CeE8Kdr^z8XqF0 z#LxL2>Q{3$xqmQuqc~lh$Ye9*hw}ItpY?a^SZA@3#l?wc+eAb5nCvzE!ZX#SeTW5RxDvF$pp#_-UWr_q%bY+Ue8c0U=9@JwC{UWTSpG zTdh~UcDIc^wb)aOOB{Xa<7p2uVjImy*gR~W$00Zt$w`oSKew2hW-5^2jwrdNv>KH_ z@_x!c(rJC5Q~I^ZnbpeU$`?xb9CCpZj@hJnh9CXsPrd^?wW2+7*yS<+00003L_t(IjqQ@ZYZGw*#XtA`ak*TtNt7&BXrO^sq7^EF3Q`>6 zpu4M+!9|=pI_f{5#7U73LMMkh>!L#|Z3=~27fXH+P@>mVj!VD!CU*`ZqMKb@{JB-|li%*G8 z+NnxktlwRKkIxfERM9-6%|3wB?RM|a(}f_sm$bZISN4@HK|zLTE$p{85wM1IUF5gFeEy`T1(uE9onn_I4p8g zxoWw1tjNO50?n|=U_3x)G$JENGbyQ?B7A`kG<%J`ByPoH4p?H7hmscCqAVtdc6hN9 zcAO}VFhheG8fB_v! z%AWF7R|oo~=Xpk>=SX4uSfXNfBxh<;whk)Ng$0Z00000NkvXXu0mjf Dv6tSQ diff --git a/docs/graphics/babl-48x48.png b/docs/graphics/babl-48x48.png index 7a8e1cc885e3c42b0f99694743a3f18edc8a0b8b..717e95d4d517f0e086773a1c6171219d880379b5 100644 GIT binary patch delta 1861 zcmV-L2fFy}4(1M!Hh&vQL_t(&f$f+7Yn9g>$6ue%IZxEYB*wTID=rCIO&77wp}06m zEo0IR$_De7u?_|@kd1+kc4PaYrGJ3kN*QfoV=#n4VYX|f+qzlln2>3tQ#4KeF41aY z;>|VQ#QQwwoc-`T_sJJyntlQO;lA&E_?+i*p3D1vKA+F~JbwqOsG^E0s`v~r_nW}H z&_)Z5{FtR!3S7S5bmosWtfrkm(atFC{2S1jQ|x`9_3`*B5qJ0*3BSg(01tS63HX^) zA3OnFv{L2($|DE?0pI|a`Oj?AAFLjDoJ~0Xfu{`shY$z^zE6SS*&catGO&YAV%|Ym zoL9OMQ2xaQ`hV~B*ryk;6SKa3{aOjK-bS`1NT@fFsW)Q8i!TyURP?$;a;m4Nr=Qnw z_x!IXsVC;o2=!=AJZ)Lwk8{zGc@usPU43o!*NmF)Mm5nltg#(7vJ1or)>_mkqJpTP zs#FLB33&BopwEf>XOQrE&&{4AJU68wzr*i|`5|Q>CVx;S5EFqTjQH(L5AS#vBBWS>jPfJU z>R(Ds^1I$cy~~L?NsP&frx6kk)60%|XW-_|n;U@_y${bF!hnF{T zCtvlDXCme|9OD=B5->VC`fwb_$45s;7mtsZsjI7{p6{ z-5TQAzdXxOX^6;1s8y`7lPfO)kH?FjCculw<9~7DQXzN>qlIwp_&J}9B}^%wK$)jG z%8PRe$Zd4*-n}mui^Z?(*|Ud}Crjf|JZdF7Q?85$blgAe*xyY^vf zYieo#LObvEzlW+~H7hGMh@|c(l4XK`kdBc|U{+FrK(r{5`sMXnxK;?h>>-d|p0~Ne z(SNxFO7Tuz&x44j+D(6DLkmDBPs6v7WB3E;?E|Sl+Ol z!CQmG665g*Y5h+tpNweGELO;ekP}&0w~+QN?Rxgzvo5#*f}k|dMINTSTf}iZxMIZ$ zT3cHISh;c~O-)VQxpRl%;dBof8M%S?j(?${Atoj!@ZQs0+e{qC#O0WBxlB1O6UQ-0 zoZw=IOR~$Q(L0ZGj^G16WX&DYaqW^?X=-ay6vpEF>hlAkwBh$3@D|v zPBg*+a~m!=PJeWoga127DSs}ZMp4x~ ziV9+;l#n6ck%I;>2p?*NHCFMba*seJaW-b5fF$uO3Ze8iRTnRH``V9P);Nh zPwDdS6oU_|XRP|&nQ*Kl@NF76 z#7#!#e4UPVL|Y8z1(Yt;$rrV$B9L@-^Ho(zo6<_&oMI*IkLdVgY|%q?Py#Eej8fP^a~oT86|^EwYKdScNwQQ3>KLsjc?0W%ss zKM&Y!b?v0X=v3F0lLhf7L(hIro!b{s$U>$5>e3Q2)(f!?^$1@^X_{)E zB6kTG5i5OS<)pFZ?RX-7XW)f_@y|;9(+QXb%YLwIg%j6o#Xc?x5*n?wXwXr&*cBE| zEF8Y{>ZOl952966QAHJ1R8d70Ra8;M=Z^mab`*V*=GDGS00000NkvXXu0mjfm}Z{a delta 1868 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

^eHF%uK zx~T&P-AazYj`gS9=($YXqNV8q;MT!jaERf%0b@&CGwZS{p2Va2RC;^!`8(9a`ql8A zLdFXsbQ+I^nxd1{+3Cp9Sx0_XbJz6Akma}Lj*IPQ*gQvJuZPDzUwY3=zvkyvf%TiB zy$CDI7H98M-}T4H=r$~umHIYTZo!3Bdz}CHryZ7@&E+u@Okn#GjfN1)_Th?LcRy<( zLnhXzGn|?08Lx&3@!+c(DkhYQqm&rbJK5CuV&?sn8I>hU>q)cps>n#Z4CF{P!ES}X>nqiMr0zqWl3O4Iz=-0bc8 zjSdJD_vRN(z%Fgl#WqiP=g%-bnWgM@HP-dX-iAY??Bft-yl2JT^Z2T^b^BTp`5iKj zgMqaO{LA3e?d#!@ZN{Z{f(BYnaNz>Zg@{gL>_kZGs|PguHGqm5!}vRGfRMNwUFr0Ty{d*UHFIhsOiOdnVCM+KiOiNfd9WAwPSq z-Y_u@Bf>z`Tc~gnD1xPuu_uggphtmn2aMUDz%C3}YN@sm3yaOJaU-=bkzo27b*rt+mM`ad7zsCIpQW+DV+L zX2ITtgt!yG4lYnTPQZ(mu!FZEE+!@tWEvaSf9VF7 za{I(1)2w&9X)Go3pb#>bLH}gCgkv>lVq9oOA011`NJggne#>`m-$aTOg-9W4`?J&Z zCKy7^#GzZQ?O0Rg)hOGjpfF0?jbe6T)4z-e1ilJ{lf)avfX!r5ozdn*OA9 z--;dL|H5_6SoTWC8Z59xjcF_K2(g(ehs-L{M}2c=vM=qX-?Jp%AgQ-By@Sz~?rXM3 zX?yUN^!V@NQmW)6hNrj97+{7*p|#=_JgcR%CMyOMGrqZuK14y9U0oGwnc`EdMaByt zWNIm!`dSMox&C7i1@BS*GpV%<_IqmkOl=6|2XxAj-2*&n0VYwCZPPhF@Z1( zaxJ=kML#32YxUvpdl8bDdr1&GD%~4@fax%>JnnDsce4}c?IJIany)ue*b|z~kaHfY zqvk{s6-Dj|3isdqd$kWn4ryt%t%;331Rh!aWB&rAZxY?m@y-EGIlnru{u2$&JtX(=*LjnNE! zd3WN~!ao#J!Qzg66DT(9^i&O#uiZnS^AVn^lDIeZvaijuD5GuQu}u~`qJBD2z^q2g zGx{5$CU31bMN8#9Kz!C=K+k>l_|mY&rxi)ptb?QQ2F5DuoE4g`pVz8#5c?ZF-rq#c z!8#^uIZ6E??h*_U!_dyrG!!_Fjuqbe7ldX#~w;>SaSl$UH)e9G^=eFDkG7rz4In=s%5yEt`R9|*A+;754rL)gOPt=yvxwX zdRbmU!E`qG8sT(-)}aHH-LdUa#{Hm6)H(N4y4gUj#bF=aX^% zu8A4N|7IvH;IkSw_&*H;Tjde|$U>+fWE=`Acus>3Zz+-cf(z#1zW|6j3jEUm^6|T0q<%pO zHK&TmDa?SeOkL%9nU4vp^+Sn@9`PJOy^()~r35BA`dQr#+F2sG*Q?K|$2Zh46F$HM z83XMsdnK8?Aul_+N1lEH`Y;Fp@)-k|Ot7JUO9bda{F@b(+nBvxq4w9@12%7Ay;pke zZ_|d`W*c0B^EA>+xJ$)rl{fj4E9-*~zm%hLalB-Mhts)a>Gs(>DuEPv5E6_zlZDNB z&JZ0%m|3EO#}$Q#ZL)g@8fGZqv|}*6GxHDZ~=^%A~pKO)m3{yTjD8tJNc%U zU=G5CH7QtZ^z^*``aHnfr(rKzN6<}`NiPTNX~D)f-Wz}IC=k(CeU4@4YVF^td>zgnH&b_Uy;?t zfSE8A^ih;XoU$-pH`B(ap%64)GfoZ<KpsL=$z~=r* zep^aH{WDKN7)F+Cv$?(Z*=d0=C$4*uGpbRVqP421481@Z5 zd~GNIz6M-6>x|)@nd2uChANmm727R1q9IB9UOE;@cYf$uN*&3rK%TK95Pm3Kc_I;C z&pi`K!{`xR#Q33tPEn~zQi2xA-_Ir}VlKz@rI1R#f)JJp(ULNQiCCB3A@kuog?@*( zCRo&F$%u)k<>~Vmoy^a)Lj5%NoA+TrBl}xsW<8*h{s;Vb6r#q^#E9WF+Pdgz&&D4F zUq<7Z)ZS9tOB06^^E&MN*8bkY!Lhu0Adq%k>E50}Meq+~QyKmc+6r6hMti6cVE9*p z7Ly=ayLv15eT5n+mS*3-nW}q;qDXI8#jpUn4L5%64X;|qGMpB zHOzSxCQr!cYB2O(`c`okEM){O7aekRdo?gfCH58IyZnDT!b~fC}6IR!?sTQS5-@B-i7620=o5kn+ zM;>%}o~Ml18^1y2FP41Ns(iT{5b>`B@?&CweW(R7B~4O|3VO`fDBap-&M$T7)YGt@ zXd9sWDz@%NeqLuS5K0XV>k2XWOB@l9g5F_K+Y7^MbmcmfN^9|64Uxh;*a*3?`YYeg z(%pGe;a>+*&wpNbc&Dbbn7Cv@Tq>%7U=w4__Yl#_H#>i;nqORnX{I~Ep}H#EtjcI- zsOs&HlFJqUgUoX8Ze8%xEh-@!()Wp3pj2*rPPU~CdABsNO}t^Vz5b}Mzw_w4+J3Z)^Gm zm>K6$*o=JQsX7}o#4?jSm>oP!`ioCIQ;w<2fOQB2amg~tv#5-Rn95kBt^(w?lw4NSq~t` zHshDAQ}myQ{1-H^X~lP&A2TYkp4Hap$(kHFTrT@~msuK3KmX^=%5X&71g8J7tR?7(xZYl{DCI;UbmyYb7_28s#)dJg!=iTB`oq%POB;IDEHOmA*5J{*RoWY=Cn)r;D=O)VReL zl*|DtjhPX<&tiSczAiX^I1Nn{(o#kXhn94TH9NFAdbK0h1|id(i5eO$9(L(ZY^bXA zHDv_`m~8FkB5r;{>V^nB-=MCpuXn;Qg}|C7AS@gU1}p=VYJnR4>B-6LESc5EQjM>S zo}G*G%QZ`=W)z6QWCPB}Y^aL_>Hyo=3dn@sZ_!&wE^tKEoL_rJ&a>eGB1iLBnC_E&@W010I z94#;>Qj;Z(SgufwA63F)xv7q6xM1449!UO?pUJ$fu++sz3J}~rPrBUtWIp>kFPUdn6LNZhr;#-j z6O^UM5?5^wmeh#B&hv%VK+eOYGLxg1m|Yk#8N?`;x!#kc5X;+*Me$u{!Fyt{To}Ry zk(RKd)~U;OVav61ePqM!D1%2YWJ&;_`GAQ;DeG=IMJhGU$^h2{w$aa0l>S#7cV0aH)AlBr)H%J*cx*zgit- zS`qgI7Sa6SMorge@3L@64lRUMUmmj83IQo9@69lLD@#jhoPRsW$I{WB}$>Wy&PiPv3v#>3hJ=r6a~5#&` z`ulVABw|L1tsa(*AbfM}G}f*dAC?}%7Oq2_-@rr3S>4ob{Ig~!LsqW4)@ z$*b#D8?^gA?Edq;@dryxiNkh#3l2Jw&L&TCc(nBb+`u-30arAxT`$i^ zd_&0iarA8!@=fr?73}?pVqf2oy}~gE8lw_R1>JvM#dvx~&?2eOnZm_FLvs}%U5o}g zthmT_=GV6xV-;Sua;sNFXX3 z2t!&!Fx?9JC-1b_1O7b28{*6c+V{|YTtlLFwmM_6ea&9|Yv9--a_ONgbQYsHUY0iA zMU?s!e#(bb(QfP0V($|b41u8XOt#^ncbZ~pDF65IcvXl(fTPNZ1Oa2kP3B>uQ|M-| z>!Kq#d%mcvT%wn)N=c!V!Y(MX8Vc+xJ%A|t4&XH;)^C5RgjK{u=INx&1vB2_t!hxO zBh*Nxc#vA-C&CUDLi^ng{uiw8pY4X3SN{`_SfKhkh%vHQKY{HCT!@Dhg-MDs$wlHX z@=Ri^T*f3yQk&3R@eLo>-4&Yaj$$KJKs~d?6SqdAgtaj6a5j43$=W+VKlc^>jt@eY ze~uUHX*DRLC)xUI*lCg7RJIZ1pcBiX?D86_eKlWmtShbk{n5i#P>sk*XJJjh_YA2# z_9j=uS$92zRDX+FujxsBL&%0FPeX9>_T0|1FRxR)AjafQK9|IX#S4n*gM+q6=jP_- zzs%sn;nUL-GZ1lD5=@#v*ha|~gb$=oB&Yi3Hi8(}fXE93u zp{B$Je&pAe3<(%nYswjK?$adAtpph|dI;a;Kl=V<*K?Z)E4$`L9?Ni(8tcQ0<=(=c z!~w`$$j7NqT9c~98wf>^J4v2}b$Q{Az}f9T|E(ndaC@!cURY-aM3V7NrxS0!G{$|G zwCeIj-^m8HU+`wvQ=NqAgi_IkFCt_B+m-p5CBsWFVX zfX{jR4e!aqRH7Q{)h*&c?UKY3bUE(Z1cUW$L#9^0O5(kiM91A>u@XvLq(N#XS`ejz z#!RITt0+RDDV!_o?kk?k`^BT`X;ygAgt@E*qh0(3v?qCtGb9scO@&fC4wBzSBbBPq zL8LGCI-jods>NBnDSO#+6o#A z_o%|R!?kKgKfd0%yn9Nz`Mkucib3gc0wJGJotN-Ko$}vaz*f~CHGmC@uJwv8G z7KcI^ISCT+n_oz1$FTa{$Tzmj?~=I7O_g8@)>LI>0Y;u*KUak25T<$z1$;veCCgR>nE#h z1Wrfp^Xj$MP*Z7;NqTk?cyx?_YvAW+&yE3?s@O>I@GPBj=KT5eUbp7iXO{(e^?qy= zwqcQzFU|tq543yJrlO~naS>WmF9A;={khM6W3Khu5Uq=^US*|MS68P^O<5qZq3I8c yjJ$mH+p^orN LAB_EPSILON ? cbrtf (xr) : (LAB_KAPPA * xr + 16.0f) / 116.0f; + float fy = yr > LAB_EPSILON ? cbrtf (yr) : (LAB_KAPPA * yr + 16.0f) / 116.0f; + float fz = zr > LAB_EPSILON ? cbrtf (zr) : (LAB_KAPPA * zr + 16.0f) / 116.0f; + + float L = 116.0f * fy - 16.0f; + float A = 500.0f * (fx - fy); + float B = 200.0f * (fy - fz); + + dst[0] = L; + dst[1] = A; + dst[2] = B; + + src += 3; + dst += 3; + } + + return samples; +} + static long rgbaf_to_Labaf (float *src, float *dst, @@ -505,6 +541,42 @@ rgbaf_to_Labaf (float *src, return samples; } +static long +Labf_to_rgbf (float *src, + float *dst, + long samples) +{ + long n = samples; + + while (n--) + { + float L = src[0]; + float A = src[1]; + float B = src[2]; + + float fy = (L + 16.0f) / 116.0f; + float fx = fy + A / 500.0f; + float fz = fy - B / 200.0f; + + float yr = L > LAB_KAPPA * LAB_EPSILON ? cubef (fy) : L / LAB_KAPPA; + float xr = cubef (fx) > LAB_EPSILON ? cubef (fx) : (fx * 116.0f - 16.0f) / LAB_KAPPA; + float zr = cubef (fz) > LAB_EPSILON ? cubef (fz) : (fz * 116.0f - 16.0f) / LAB_KAPPA; + + float r = 3.134274799724f * D50_WHITE_REF_X * xr -1.617275708956f * D50_WHITE_REF_Y * yr -0.490724283042f * D50_WHITE_REF_Z * zr; + float g = -0.978795575994f * D50_WHITE_REF_X * xr +1.916161689117f * D50_WHITE_REF_Y * yr +0.033453331711f * D50_WHITE_REF_Z * zr; + float b = 0.071976988401f * D50_WHITE_REF_X * xr -0.228984974402f * D50_WHITE_REF_Y * yr +1.405718224383f * D50_WHITE_REF_Z * zr; + + dst[0] = r; + dst[1] = g; + dst[2] = b; + + src += 3; + dst += 3; + } + + return samples; +} + static long Labaf_to_rgbaf (float *src, float *dst, @@ -570,6 +642,18 @@ conversions (void) "linear", laba_to_rgba, NULL ); + babl_conversion_new ( + babl_format ("RGB float"), + babl_format ("CIE Lab float"), + "linear", rgbf_to_Labf, + NULL + ); + babl_conversion_new ( + babl_format ("CIE Lab float"), + babl_format ("RGB float"), + "linear", Labf_to_rgbf, + NULL + ); babl_conversion_new ( babl_format ("RGBA float"), babl_format ("CIE Lab alpha float"), diff --git a/extensions/Makefile.am b/extensions/Makefile.am index 4a3fb8a..7ecb457 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -17,8 +17,11 @@ extdir = $(libdir)/babl-@BABL_API_VERSION@ ext_LTLIBRARIES = \ cairo.la \ CIE.la \ + float-half.la \ gegl-fixups.la \ gggl-lies.la \ + gggl-table.la \ + gggl-table-lies.la \ gggl.la \ gimp-8bit.la \ grey.la \ @@ -31,14 +34,19 @@ ext_LTLIBRARIES = \ sse2-float.la \ sse2-int8.la \ sse2-int16.la \ + sse4-int8.la \ + sse-half.la \ two-table.la \ ycbcr.la cairo_la_SOURCES = cairo.c cairo-tables.h CIE_la_SOURCES = CIE.c simple_la_SOURCES = simple.c +float_half_la_SOURCES = float-half.c gegl_fixups_la_SOURCES = gegl-fixups.c gggl_lies_la_SOURCES = gggl-lies.c +gggl_table_lies_la_SOURCES = gggl-table-lies.c +gggl_table_la_SOURCES = gggl-table.c gggl_la_SOURCES = gggl.c gimp_8bit_la_SOURCES = gimp-8bit.c grey_la_SOURCES = grey.c @@ -48,6 +56,8 @@ HSV_la_SOURCES = HSV.c sse2_float_la_SOURCES = sse2-float.c sse2_int8_la_SOURCES = sse2-int8.c sse2_int16_la_SOURCES = sse2-int16.c +sse4_int8_la_SOURCES = sse4-int8.c +sse_half_la_SOURCES = sse-half.c two_table_la_SOURCES = two-table.c two-table-tables.h ycbcr_la_SOURCES = ycbcr.c float_la_SOURCES = float.c @@ -59,3 +69,5 @@ LIBS = $(top_builddir)/babl/libbabl-@BABL_API_VERSION@.la $(MATH_LIB) \ sse2_float_la_CFLAGS = $(SSE2_EXTRA_CFLAGS) sse2_int8_la_CFLAGS = $(SSE2_EXTRA_CFLAGS) sse2_int16_la_CFLAGS = $(SSE2_EXTRA_CFLAGS) +sse4_int8_la_CFLAGS = $(SSE4_1_EXTRA_CFLAGS) +sse_half_la_CFLAGS = $(SSE4_1_EXTRA_CFLAGS) $(F16C_EXTRA_CFLAGS) diff --git a/extensions/Makefile.in b/extensions/Makefile.in index fa3d0df..0ba5216 100644 --- a/extensions/Makefile.in +++ b/extensions/Makefile.in @@ -152,6 +152,9 @@ cairo_la_OBJECTS = $(am_cairo_la_OBJECTS) fast_float_la_LIBADD = am_fast_float_la_OBJECTS = fast-float.lo fast_float_la_OBJECTS = $(am_fast_float_la_OBJECTS) +float_half_la_LIBADD = +am_float_half_la_OBJECTS = float-half.lo +float_half_la_OBJECTS = $(am_float_half_la_OBJECTS) float_la_LIBADD = am_float_la_OBJECTS = float.lo float_la_OBJECTS = $(am_float_la_OBJECTS) @@ -161,6 +164,12 @@ gegl_fixups_la_OBJECTS = $(am_gegl_fixups_la_OBJECTS) gggl_lies_la_LIBADD = am_gggl_lies_la_OBJECTS = gggl-lies.lo gggl_lies_la_OBJECTS = $(am_gggl_lies_la_OBJECTS) +gggl_table_lies_la_LIBADD = +am_gggl_table_lies_la_OBJECTS = gggl-table-lies.lo +gggl_table_lies_la_OBJECTS = $(am_gggl_table_lies_la_OBJECTS) +gggl_table_la_LIBADD = +am_gggl_table_la_OBJECTS = gggl-table.lo +gggl_table_la_OBJECTS = $(am_gggl_table_la_OBJECTS) gggl_la_LIBADD = am_gggl_la_OBJECTS = gggl.lo gggl_la_OBJECTS = $(am_gggl_la_OBJECTS) @@ -176,6 +185,12 @@ naive_CMYK_la_OBJECTS = $(am_naive_CMYK_la_OBJECTS) simple_la_LIBADD = am_simple_la_OBJECTS = simple.lo simple_la_OBJECTS = $(am_simple_la_OBJECTS) +sse_half_la_LIBADD = +am_sse_half_la_OBJECTS = sse_half_la-sse-half.lo +sse_half_la_OBJECTS = $(am_sse_half_la_OBJECTS) +sse_half_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(sse_half_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ sse2_float_la_LIBADD = am_sse2_float_la_OBJECTS = sse2_float_la-sse2-float.lo sse2_float_la_OBJECTS = $(am_sse2_float_la_OBJECTS) @@ -194,6 +209,12 @@ sse2_int8_la_OBJECTS = $(am_sse2_int8_la_OBJECTS) sse2_int8_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(sse2_int8_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +sse4_int8_la_LIBADD = +am_sse4_int8_la_OBJECTS = sse4_int8_la-sse4-int8.lo +sse4_int8_la_OBJECTS = $(am_sse4_int8_la_OBJECTS) +sse4_int8_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(sse4_int8_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ two_table_la_LIBADD = am_two_table_la_OBJECTS = two-table.lo two_table_la_OBJECTS = $(am_two_table_la_OBJECTS) @@ -236,21 +257,25 @@ am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(CIE_la_SOURCES) $(HSL_la_SOURCES) $(HSV_la_SOURCES) \ $(cairo_la_SOURCES) $(fast_float_la_SOURCES) \ - $(float_la_SOURCES) $(gegl_fixups_la_SOURCES) \ - $(gggl_lies_la_SOURCES) $(gggl_la_SOURCES) \ - $(gimp_8bit_la_SOURCES) $(grey_la_SOURCES) \ + $(float_half_la_SOURCES) $(float_la_SOURCES) \ + $(gegl_fixups_la_SOURCES) $(gggl_lies_la_SOURCES) \ + $(gggl_table_lies_la_SOURCES) $(gggl_table_la_SOURCES) \ + $(gggl_la_SOURCES) $(gimp_8bit_la_SOURCES) $(grey_la_SOURCES) \ $(naive_CMYK_la_SOURCES) $(simple_la_SOURCES) \ - $(sse2_float_la_SOURCES) $(sse2_int16_la_SOURCES) \ - $(sse2_int8_la_SOURCES) $(two_table_la_SOURCES) \ + $(sse_half_la_SOURCES) $(sse2_float_la_SOURCES) \ + $(sse2_int16_la_SOURCES) $(sse2_int8_la_SOURCES) \ + $(sse4_int8_la_SOURCES) $(two_table_la_SOURCES) \ $(ycbcr_la_SOURCES) DIST_SOURCES = $(CIE_la_SOURCES) $(HSL_la_SOURCES) $(HSV_la_SOURCES) \ $(cairo_la_SOURCES) $(fast_float_la_SOURCES) \ - $(float_la_SOURCES) $(gegl_fixups_la_SOURCES) \ - $(gggl_lies_la_SOURCES) $(gggl_la_SOURCES) \ - $(gimp_8bit_la_SOURCES) $(grey_la_SOURCES) \ + $(float_half_la_SOURCES) $(float_la_SOURCES) \ + $(gegl_fixups_la_SOURCES) $(gggl_lies_la_SOURCES) \ + $(gggl_table_lies_la_SOURCES) $(gggl_table_la_SOURCES) \ + $(gggl_la_SOURCES) $(gimp_8bit_la_SOURCES) $(grey_la_SOURCES) \ $(naive_CMYK_la_SOURCES) $(simple_la_SOURCES) \ - $(sse2_float_la_SOURCES) $(sse2_int16_la_SOURCES) \ - $(sse2_int8_la_SOURCES) $(two_table_la_SOURCES) \ + $(sse_half_la_SOURCES) $(sse2_float_la_SOURCES) \ + $(sse2_int16_la_SOURCES) $(sse2_int8_la_SOURCES) \ + $(sse4_int8_la_SOURCES) $(two_table_la_SOURCES) \ $(ycbcr_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ @@ -318,6 +343,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -363,6 +389,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ @@ -440,8 +467,11 @@ extdir = $(libdir)/babl-@BABL_API_VERSION@ ext_LTLIBRARIES = \ cairo.la \ CIE.la \ + float-half.la \ gegl-fixups.la \ gggl-lies.la \ + gggl-table.la \ + gggl-table-lies.la \ gggl.la \ gimp-8bit.la \ grey.la \ @@ -454,14 +484,19 @@ ext_LTLIBRARIES = \ sse2-float.la \ sse2-int8.la \ sse2-int16.la \ + sse4-int8.la \ + sse-half.la \ two-table.la \ ycbcr.la cairo_la_SOURCES = cairo.c cairo-tables.h CIE_la_SOURCES = CIE.c simple_la_SOURCES = simple.c +float_half_la_SOURCES = float-half.c gegl_fixups_la_SOURCES = gegl-fixups.c gggl_lies_la_SOURCES = gggl-lies.c +gggl_table_lies_la_SOURCES = gggl-table-lies.c +gggl_table_la_SOURCES = gggl-table.c gggl_la_SOURCES = gggl.c gimp_8bit_la_SOURCES = gimp-8bit.c grey_la_SOURCES = grey.c @@ -471,6 +506,8 @@ HSV_la_SOURCES = HSV.c sse2_float_la_SOURCES = sse2-float.c sse2_int8_la_SOURCES = sse2-int8.c sse2_int16_la_SOURCES = sse2-int16.c +sse4_int8_la_SOURCES = sse4-int8.c +sse_half_la_SOURCES = sse-half.c two_table_la_SOURCES = two-table.c two-table-tables.h ycbcr_la_SOURCES = ycbcr.c float_la_SOURCES = float.c @@ -478,6 +515,8 @@ fast_float_la_SOURCES = fast-float.c sse2_float_la_CFLAGS = $(SSE2_EXTRA_CFLAGS) sse2_int8_la_CFLAGS = $(SSE2_EXTRA_CFLAGS) sse2_int16_la_CFLAGS = $(SSE2_EXTRA_CFLAGS) +sse4_int8_la_CFLAGS = $(SSE4_1_EXTRA_CFLAGS) +sse_half_la_CFLAGS = $(SSE4_1_EXTRA_CFLAGS) $(F16C_EXTRA_CFLAGS) all: all-am .SUFFIXES: @@ -562,6 +601,9 @@ cairo.la: $(cairo_la_OBJECTS) $(cairo_la_DEPENDENCIES) $(EXTRA_cairo_la_DEPENDEN fast-float.la: $(fast_float_la_OBJECTS) $(fast_float_la_DEPENDENCIES) $(EXTRA_fast_float_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(fast_float_la_OBJECTS) $(fast_float_la_LIBADD) $(LIBS) +float-half.la: $(float_half_la_OBJECTS) $(float_half_la_DEPENDENCIES) $(EXTRA_float_half_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(float_half_la_OBJECTS) $(float_half_la_LIBADD) $(LIBS) + float.la: $(float_la_OBJECTS) $(float_la_DEPENDENCIES) $(EXTRA_float_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(float_la_OBJECTS) $(float_la_LIBADD) $(LIBS) @@ -571,6 +613,12 @@ gegl-fixups.la: $(gegl_fixups_la_OBJECTS) $(gegl_fixups_la_DEPENDENCIES) $(EXTRA gggl-lies.la: $(gggl_lies_la_OBJECTS) $(gggl_lies_la_DEPENDENCIES) $(EXTRA_gggl_lies_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(gggl_lies_la_OBJECTS) $(gggl_lies_la_LIBADD) $(LIBS) +gggl-table-lies.la: $(gggl_table_lies_la_OBJECTS) $(gggl_table_lies_la_DEPENDENCIES) $(EXTRA_gggl_table_lies_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(gggl_table_lies_la_OBJECTS) $(gggl_table_lies_la_LIBADD) $(LIBS) + +gggl-table.la: $(gggl_table_la_OBJECTS) $(gggl_table_la_DEPENDENCIES) $(EXTRA_gggl_table_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(gggl_table_la_OBJECTS) $(gggl_table_la_LIBADD) $(LIBS) + gggl.la: $(gggl_la_OBJECTS) $(gggl_la_DEPENDENCIES) $(EXTRA_gggl_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(gggl_la_OBJECTS) $(gggl_la_LIBADD) $(LIBS) @@ -586,6 +634,9 @@ naive-CMYK.la: $(naive_CMYK_la_OBJECTS) $(naive_CMYK_la_DEPENDENCIES) $(EXTRA_na simple.la: $(simple_la_OBJECTS) $(simple_la_DEPENDENCIES) $(EXTRA_simple_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(simple_la_OBJECTS) $(simple_la_LIBADD) $(LIBS) +sse-half.la: $(sse_half_la_OBJECTS) $(sse_half_la_DEPENDENCIES) $(EXTRA_sse_half_la_DEPENDENCIES) + $(AM_V_CCLD)$(sse_half_la_LINK) -rpath $(extdir) $(sse_half_la_OBJECTS) $(sse_half_la_LIBADD) $(LIBS) + sse2-float.la: $(sse2_float_la_OBJECTS) $(sse2_float_la_DEPENDENCIES) $(EXTRA_sse2_float_la_DEPENDENCIES) $(AM_V_CCLD)$(sse2_float_la_LINK) -rpath $(extdir) $(sse2_float_la_OBJECTS) $(sse2_float_la_LIBADD) $(LIBS) @@ -595,6 +646,9 @@ sse2-int16.la: $(sse2_int16_la_OBJECTS) $(sse2_int16_la_DEPENDENCIES) $(EXTRA_ss sse2-int8.la: $(sse2_int8_la_OBJECTS) $(sse2_int8_la_DEPENDENCIES) $(EXTRA_sse2_int8_la_DEPENDENCIES) $(AM_V_CCLD)$(sse2_int8_la_LINK) -rpath $(extdir) $(sse2_int8_la_OBJECTS) $(sse2_int8_la_LIBADD) $(LIBS) +sse4-int8.la: $(sse4_int8_la_OBJECTS) $(sse4_int8_la_DEPENDENCIES) $(EXTRA_sse4_int8_la_DEPENDENCIES) + $(AM_V_CCLD)$(sse4_int8_la_LINK) -rpath $(extdir) $(sse4_int8_la_OBJECTS) $(sse4_int8_la_LIBADD) $(LIBS) + two-table.la: $(two_table_la_OBJECTS) $(two_table_la_DEPENDENCIES) $(EXTRA_two_table_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extdir) $(two_table_la_OBJECTS) $(two_table_la_LIBADD) $(LIBS) @@ -612,9 +666,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HSV.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fast-float.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/float-half.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/float.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gegl-fixups.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gggl-lies.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gggl-table-lies.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gggl-table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gggl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimp-8bit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grey.Plo@am__quote@ @@ -623,6 +680,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sse2_float_la-sse2-float.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sse2_int16_la-sse2-int16.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sse2_int8_la-sse2-int8.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sse4_int8_la-sse4-int8.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sse_half_la-sse-half.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two-table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ycbcr.Plo@am__quote@ @@ -647,6 +706,13 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +sse_half_la-sse-half.lo: sse-half.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sse_half_la_CFLAGS) $(CFLAGS) -MT sse_half_la-sse-half.lo -MD -MP -MF $(DEPDIR)/sse_half_la-sse-half.Tpo -c -o sse_half_la-sse-half.lo `test -f 'sse-half.c' || echo '$(srcdir)/'`sse-half.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sse_half_la-sse-half.Tpo $(DEPDIR)/sse_half_la-sse-half.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sse-half.c' object='sse_half_la-sse-half.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sse_half_la_CFLAGS) $(CFLAGS) -c -o sse_half_la-sse-half.lo `test -f 'sse-half.c' || echo '$(srcdir)/'`sse-half.c + sse2_float_la-sse2-float.lo: sse2-float.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sse2_float_la_CFLAGS) $(CFLAGS) -MT sse2_float_la-sse2-float.lo -MD -MP -MF $(DEPDIR)/sse2_float_la-sse2-float.Tpo -c -o sse2_float_la-sse2-float.lo `test -f 'sse2-float.c' || echo '$(srcdir)/'`sse2-float.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sse2_float_la-sse2-float.Tpo $(DEPDIR)/sse2_float_la-sse2-float.Plo @@ -668,6 +734,13 @@ sse2_int8_la-sse2-int8.lo: sse2-int8.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sse2_int8_la_CFLAGS) $(CFLAGS) -c -o sse2_int8_la-sse2-int8.lo `test -f 'sse2-int8.c' || echo '$(srcdir)/'`sse2-int8.c +sse4_int8_la-sse4-int8.lo: sse4-int8.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sse4_int8_la_CFLAGS) $(CFLAGS) -MT sse4_int8_la-sse4-int8.lo -MD -MP -MF $(DEPDIR)/sse4_int8_la-sse4-int8.Tpo -c -o sse4_int8_la-sse4-int8.lo `test -f 'sse4-int8.c' || echo '$(srcdir)/'`sse4-int8.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sse4_int8_la-sse4-int8.Tpo $(DEPDIR)/sse4_int8_la-sse4-int8.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sse4-int8.c' object='sse4_int8_la-sse4-int8.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sse4_int8_la_CFLAGS) $(CFLAGS) -c -o sse4_int8_la-sse4-int8.lo `test -f 'sse4-int8.c' || echo '$(srcdir)/'`sse4-int8.c + mostlyclean-libtool: -rm -f *.lo diff --git a/extensions/float-half.c b/extensions/float-half.c new file mode 100644 index 0000000..ff37625 --- /dev/null +++ b/extensions/float-half.c @@ -0,0 +1,356 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2015 Daniel Sabo + * 2016 Øyvind Kolås + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see + * . + */ + +/* Copyright: (c) 2009 by James Tursa, All Rights Reserved + * + * This code uses the BSD License: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * halfprecision converts the input argument to/from a half precision floating + * point bit pattern corresponding to IEEE 754r. The bit pattern is stored in a + * uint16 class variable. Please note that halfprecision is *not* a class. That + * is, you cannot do any arithmetic with the half precision bit patterns. + * halfprecision is simply a function that converts the IEEE 754r half precision + * bit pattern to/from other numeric MATLAB variables. You can, however, take + * the half precision bit patterns, convert them to single or double, do the + * operation, and then convert the result back manually. + * + * 1 bit sign bit + * 5 bits exponent, biased by 15 + * 10 bits mantissa, hidden leading bit, normalized to 1.0 + * + * Special floating point bit patterns recognized and supported: + * + * All exponent bits zero: + * - If all mantissa bits are zero, then number is zero (possibly signed) + * - Otherwise, number is a denormalized bit pattern + * + * All exponent bits set to 1: + * - If all mantissa bits are zero, then number is +Infinity or -Infinity + * - Otherwise, number is NaN (Not a Number) + */ + +#include "config.h" + +#include +#include + +#include "babl.h" +#include "extensions/util.h" + +static void halfp2singles(void *target, const void *source, long numel) +{ + uint16_t *hp = (uint16_t *) source; // Type pun input as an unsigned 16-bit int + uint32_t *xp = (uint32_t *) target; // Type pun output as an unsigned 32-bit int + uint16_t h, hs, he, hm; + uint32_t xs, xe, xm; + int32_t xes; + int e; + + if( source == NULL || target == NULL ) // Nothing to convert (e.g., imag part of pure real) + return; + while( numel-- ) { + h = *hp++; + if( (h & 0x7FFFu) == 0 ) { // Signed zero + *xp++ = ((uint32_t) h) << 16; // Return the signed zero + } else { // Not zero + hs = h & 0x8000u; // Pick off sign bit + he = h & 0x7C00u; // Pick off exponent bits + hm = h & 0x03FFu; // Pick off mantissa bits + if( he == 0 ) { // Denormal will convert to normalized + e = -1; // The following loop figures out how much extra to adjust the exponent + do { + e++; + hm <<= 1; + } while( (hm & 0x0400u) == 0 ); // Shift until leading bit overflows into exponent bit + xs = ((uint32_t) hs) << 16; // Sign bit + xes = ((int32_t) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single + xe = (uint32_t) (xes << 23); // Exponent + xm = ((uint32_t) (hm & 0x03FFu)) << 13; // Mantissa + *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits + } else if( he == 0x7C00u ) { // Inf or NaN (all the exponent bits are set) + if( hm == 0 ) { // If mantissa is zero ... + *xp++ = (((uint32_t) hs) << 16) | ((uint32_t) 0x7F800000u); // Signed Inf + } else { + *xp++ = (uint32_t) 0xFFC00000u; // NaN, only 1st mantissa bit set + } + } else { // Normalized number + xs = ((uint32_t) hs) << 16; // Sign bit + xes = ((int32_t) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single + xe = (uint32_t) (xes << 23); // Exponent + xm = ((uint32_t) hm) << 13; // Mantissa + *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits + } + } + } +} + +static void singles2halfp(void *target, const void *source, long numel) +{ + uint16_t *hp = (uint16_t *) target; // Type pun output as an unsigned 16-bit int + uint32_t *xp = (uint32_t *) source; // Type pun input as an unsigned 32-bit int + uint16_t hs, he, hm; + uint32_t x, xs, xe, xm; + int hes; + + if( source == NULL || target == NULL ) { // Nothing to convert (e.g., imag part of pure real) + return; + } + while( numel-- ) { + x = *xp++; + if( (x & 0x7FFFFFFFu) == 0 ) { // Signed zero + *hp++ = (uint16_t) (x >> 16); // Return the signed zero + } else { // Not zero + xs = x & 0x80000000u; // Pick off sign bit + xe = x & 0x7F800000u; // Pick off exponent bits + xm = x & 0x007FFFFFu; // Pick off mantissa bits + if( xe == 0 ) { // Denormal will underflow, return a signed zero + *hp++ = (uint16_t) (xs >> 16); + } else if( xe == 0x7F800000u ) { // Inf or NaN (all the exponent bits are set) + if( xm == 0 ) { // If mantissa is zero ... + *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf + } else { + *hp++ = (uint16_t) 0xFE00u; // NaN, only 1st mantissa bit set + } + } else { // Normalized number + hs = (uint16_t) (xs >> 16); // Sign bit + hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp + if( hes >= 0x1F ) { // Overflow + *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf + } else if( hes <= 0 ) { // Underflow + if( (14 - hes) > 24 ) { // Mantissa shifted all the way off & no rounding possibility + hm = (uint16_t) 0u; // Set mantissa to zero + } else { + xm |= 0x00800000u; // Add the hidden leading bit + hm = (uint16_t) (xm >> (14 - hes)); // Mantissa + if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding + hm += (uint16_t) 1u; // Round, might overflow into exp bit, but this is OK + } + *hp++ = (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero + } else { + he = (uint16_t) (hes << 10); // Exponent + hm = (uint16_t) (xm >> 13); // Mantissa + if( xm & 0x00001000u ) // Check for rounding + *hp++ = (hs | he | hm) + (uint16_t) 1u; // Round, might overflow to inf, this is OK + else + *hp++ = (hs | he | hm); // No rounding + } + } + } + } +} + +static inline long +conv_yHalf_yF (const uint16_t *src, float *dst, long samples) +{ + halfp2singles(dst, src, samples); + return samples; +} + +static long +conv_yaHalf_yaF (const uint16_t *src, float *dst, long samples) +{ + return conv_yHalf_yF (src, dst, samples * 2) / 2; +} + +static long +conv_rgbHalf_rgbF (const uint16_t *src, float *dst, long samples) +{ + return conv_yHalf_yF (src, dst, samples * 3) / 3; +} + +static long +conv_rgbaHalf_rgbaF (const uint16_t *src, float *dst, long samples) +{ + return conv_yHalf_yF (src, dst, samples * 4) / 4; +} + +static inline long +conv_yF_yHalf (const float *src, uint16_t *dst, long samples) +{ + singles2halfp (dst, src, samples); + return samples; +} + +static long +conv_yaF_yaHalf (const float *src, uint16_t *dst, long samples) +{ + return conv_yF_yHalf (src, dst, samples * 2) / 2; +} + +static long +conv_rgbF_rgbHalf (const float *src, uint16_t *dst, long samples) +{ + return conv_yF_yHalf (src, dst, samples * 3) / 3; +} + +static long +conv_rgbaF_rgbaHalf (const float *src, uint16_t *dst, long samples) +{ + return conv_yF_yHalf (src, dst, samples * 4) / 4; +} + +int init (void); + +int +init (void) +{ + const Babl *rgbaF_linear = babl_format_new ( + babl_model ("RGBA"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgbaHalf_linear = babl_format_new ( + babl_model ("RGBA"), + babl_type ("half"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgbaF_gamma = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgbaHalf_gamma = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("half"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgbF_linear = babl_format_new ( + babl_model ("RGB"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgbHalf_linear = babl_format_new ( + babl_model ("RGB"), + babl_type ("half"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgbF_gamma = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *rgbHalf_gamma = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("half"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *yaF_linear = babl_format_new ( + babl_model ("YA"), + babl_type ("float"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *yaHalf_linear = babl_format_new ( + babl_model ("YA"), + babl_type ("half"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *yaF_gamma = babl_format_new ( + babl_model ("Y'A"), + babl_type ("float"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *yaHalf_gamma = babl_format_new ( + babl_model ("Y'A"), + babl_type ("half"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *yF_linear = babl_format_new ( + babl_model ("Y"), + babl_type ("float"), + babl_component ("Y"), + NULL); + const Babl *yHalf_linear = babl_format_new ( + babl_model ("Y"), + babl_type ("half"), + babl_component ("Y"), + NULL); + const Babl *yF_gamma = babl_format_new ( + babl_model ("Y'"), + babl_type ("float"), + babl_component ("Y'"), + NULL); + const Babl *yHalf_gamma = babl_format_new ( + babl_model ("Y'"), + babl_type ("half"), + babl_component ("Y'"), + NULL); + +#define CONV(src, dst) \ +{ \ + babl_conversion_new (src ## _linear, dst ## _linear, "linear", conv_ ## src ## _ ## dst, NULL); \ + babl_conversion_new (src ## _gamma, dst ## _gamma, "linear", conv_ ## src ## _ ## dst, NULL); \ +} + + CONV(rgbaHalf, rgbaF); + CONV(rgbHalf, rgbF); + CONV(yaHalf, yaF); + CONV(yHalf, yF); + CONV(rgbaF, rgbaHalf); + CONV(rgbF, rgbHalf); + CONV(yaF, yaHalf); + CONV(yF, yHalf); + + return 0; +} diff --git a/extensions/gggl-lies.c b/extensions/gggl-lies.c index 91304d6..22d0fee 100644 --- a/extensions/gggl-lies.c +++ b/extensions/gggl-lies.c @@ -50,176 +50,6 @@ * gamma correction (not really,. gamma correction belongs in seperate ops,. */ -#define USE_TABLES -#ifdef USE_TABLES - -/* lookup tables used in conversion */ - -static float table_8_F[1 << 8]; -static float table_16_F[1 << 16]; -static unsigned char table_F_8[1 << 16]; -static unsigned short table_F_16[1 << 16]; - - -static int table_inited = 0; - -static void -table_init (void) -{ - int i; - - if (table_inited) - return; - table_inited = 1; - - /* fill tables for conversion from integer to float */ - for (i = 0; i < 1 << 8; i++) - { - table_8_F[i] = (i * 1.0) / 255.0; - } - for (i = 0; i < 1 << 16; i++) - { - table_16_F[i] = (i * 1.0) / 65535.0; - } - /* fill tables for conversion from float to integer */ - { - union - { - float f; - unsigned short s[2]; - } u; - u.f = 0.0; - - u.s[0] = 0x8000; - - for (i = 0; i < 1 << 16; i++) - { - unsigned char c; - unsigned short s; - - u.s[1] = i; - - if (u.f <= 0.0) - { - c = 0; - s = 0; - } - else if (u.f >= 1.0) - { - c = 255; - s = 65535; - } - else - { - c = lrint (u.f * 255.0); - s = lrint (u.f * 65535.0); - } - - /*fprintf (stderr, "%2.3f=%03i %05i ", f, c, (*hi)); - / if (! ((*hi)%9)) - / fprintf (stderr, "\n"); */ - - table_F_8[u.s[1]] = c; - table_F_16[u.s[1]] = s; - } - } - /* fix tables to ensure 1:1 conversions back and forth */ - if (0) - { /*FIXME: probably not the right way to do it,.. must sit down and scribble on paper */ - int i; - for (i = 0; i < 256; i++) - { - float f = table_8_F[i]; - unsigned short *hi = ((unsigned short *) (void *) &f); - unsigned short *lo = ((unsigned short *) (void *) &f); - *lo = 0; - table_F_8[(*hi)] = i; - } - } -} - -/* function to find the index in table for a float */ -static unsigned int -gggl_float_to_index16 (float f) -{ - union - { - float f; - unsigned short s[2]; - } u; - u.f = f; - return u.s[1]; -} - - -static long -conv_F_8 (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - register float f = (*(float *) src); - *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; - dst += 1; - src += 4; - } - return samples; -} - -static long -conv_F_16 (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - register float f = (*(float *) src); - *(unsigned short *) dst = table_F_16[gggl_float_to_index16 (f)]; - dst += 2; - src += 4; - } - return samples; -} - -static long -conv_8_F (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - (*(float *) dst) = table_8_F[*(unsigned char *) src]; - dst += 4; - src += 1; - } - return samples; -} - -static long -conv_16_F (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - (*(float *) dst) = table_16_F[*(unsigned short *) src]; - dst += 4; - src += 2; - } - return samples; -} - -#else - static long conv_F_8 (unsigned char *src, unsigned char *dst, long samples) { @@ -302,9 +132,6 @@ conv_16_F (unsigned char *src, unsigned char *dst, long samples) return samples; } - -#endif - static long conv_F_D (unsigned char *src, unsigned char *dst, long samples) { @@ -319,7 +146,6 @@ conv_F_D (unsigned char *src, unsigned char *dst, long samples) return samples; } - static long conv_D_F (unsigned char *src, unsigned char *dst, long samples) { @@ -1050,10 +876,5 @@ init (void) o (rgba8, rgb8); o (rgbaF, rgbA8); -#ifdef USE_TABLES - if (!table_inited) - table_init (); -#endif - return 0; } diff --git a/extensions/gggl-table-lies.c b/extensions/gggl-table-lies.c new file mode 100644 index 0000000..3e79a6f --- /dev/null +++ b/extensions/gggl-table-lies.c @@ -0,0 +1,479 @@ +/* + * This file was part of gggl, it implements a variety of pixel conversion + * functions that are usable with babl, the file needs more cleanup, and + * doesn't return the number of samples processed as a long, like it's + * supposed to. + * + * GGGL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GGGL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GGGL; if not, see . + * + * Rights are granted to use this shared object in libraries covered by + * LGPL. (exception added, during import into babl CVS.) + * + * Copyright 2003, 2004, 2005 Øyvind Kolås + */ + +#define _POSIX_C_SOURCE 200112L + +#include "config.h" +#include +#include + +#include "babl.h" +#include "extensions/util.h" + +/* + * Implemented according to information read from: + * + * http://www.cinenet.net/~spitzak/conversion/sketches_0265.pdf + * + * initially ignoring any diffusion, to keep the implementation + * smaller, and interchangeable with the non optimized version. + * + * due to ability to be able to relicence gggl under a different + * licence than GPL, I avoided the temptation to look at the + * source files in the same location, in case I was going to + * need this piece of code for projects where GPL compatibility + * was a must. + * + * TODO: error diffusion, + * gamma correction (not really,. gamma correction belongs in seperate ops,. + */ + +/* lookup tables used in conversion */ + +static float table_8_F[1 << 8]; +static float table_16_F[1 << 16]; +static unsigned char table_F_8[1 << 16]; +static unsigned short table_F_16[1 << 16]; + + +static int table_inited = 0; + +static void +table_init (void) +{ + int i; + + if (table_inited) + return; + table_inited = 1; + + /* fill tables for conversion from integer to float */ + for (i = 0; i < 1 << 8; i++) + { + table_8_F[i] = (i * 1.0) / 255.0; + } + for (i = 0; i < 1 << 16; i++) + { + table_16_F[i] = (i * 1.0) / 65535.0; + } + /* fill tables for conversion from float to integer */ + { + union + { + float f; + unsigned short s[2]; + } u; + u.f = 0.0; + + u.s[0] = 0x8000; + + for (i = 0; i < 1 << 16; i++) + { + unsigned char c; + unsigned short s; + + u.s[1] = i; + + if (u.f <= 0.0) + { + c = 0; + s = 0; + } + else if (u.f >= 1.0) + { + c = 255; + s = 65535; + } + else + { + c = lrint (u.f * 255.0); + s = lrint (u.f * 65535.0); + } + + /*fprintf (stderr, "%2.3f=%03i %05i ", f, c, (*hi)); + / if (! ((*hi)%9)) + / fprintf (stderr, "\n"); */ + + table_F_8[u.s[1]] = c; + table_F_16[u.s[1]] = s; + } + } + /* fix tables to ensure 1:1 conversions back and forth */ + if (0) + { /*FIXME: probably not the right way to do it,.. must sit down and scribble on paper */ + int i; + for (i = 0; i < 256; i++) + { + float f = table_8_F[i]; + unsigned short *hi = ((unsigned short *) (void *) &f); + unsigned short *lo = ((unsigned short *) (void *) &f); + *lo = 0; + table_F_8[(*hi)] = i; + } + } +} + +/* function to find the index in table for a float */ +static unsigned int +gggl_float_to_index16 (float f) +{ + union + { + float f; + unsigned short s[2]; + } u; + u.f = f; + return u.s[1]; +} + + +static long +conv_F_8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + register float f = (*(float *) src); + *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; + dst += 1; + src += 4; + } + return samples; +} + +static long +conv_F_16 (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + register float f = (*(float *) src); + *(unsigned short *) dst = table_F_16[gggl_float_to_index16 (f)]; + dst += 2; + src += 4; + } + return samples; +} + +static long +conv_8_F (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + (*(float *) dst) = table_8_F[*(unsigned char *) src]; + dst += 4; + src += 1; + } + return samples; +} + +static long +conv_16_F (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + (*(float *) dst) = table_16_F[*(unsigned short *) src]; + dst += 4; + src += 2; + } + return samples; +} + +/*********/ +static long +conv_rgbaF_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 4); + return samples; +} + +#define conv_rgbaF_rgbP8 conv_rgbaF_rgba8 + +static long +conv_rgbF_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 3); + return samples; +} + +static long +conv_gaF_ga8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbAF_rgbA8 conv_rgbaF_rgba8 +#define conv_gF_g8 conv_F_8 +#define conv_gAF_gA8 conv_gaF_ga8 + +static long +conv_rgbaF_rgba16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 4); + return samples; +} + +static long +conv_rgbF_rgb16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 3); + return samples; +} + +static long +conv_gaF_ga16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbAF_rgbA16 conv_rgbaF_rgba16 +#define conv_gF_g16 conv_F_16 +#define conv_gAF_gA16 conv_gaF_ga16 + +static long +conv_rgba8_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_F (src, dst, samples * 4); + return samples; +} + +static long +conv_rgb8_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_F (src, dst, samples * 3); + return samples; +} + +static long +conv_ga8_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_F (src, dst, samples * 2); + return samples; +} + +#define conv_rgbA8_rgbAF conv_rgba8_rgbaF +#define conv_gA8_gAF conv_ga8_gaF +#define conv_g8_gF conv_8_F + +static long +conv_rgba16_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 4); + return samples; +} + +static long +conv_rgb16_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 3); + return samples; +} + +static long +conv_ga16_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 2); + return samples; +} + +#define conv_rgbA16_rgbAF conv_rgba16_rgbaF +#define conv_gA16_gAF conv_ga16_gaF +#define conv_g16_gF conv_16_F + +int init (void); + +int +init (void) +{ + const Babl *rgbaF = babl_format_new ( + babl_model ("RGBA"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgba16 = babl_format_new ( + babl_model ("RGBA"), + babl_type ("u16"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgba8 = babl_format_new ( + babl_model ("RGBA"), + babl_type ("u8"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgbAF = babl_format_new ( + babl_model ("RaGaBaA"), + babl_type ("float"), + babl_component ("Ra"), + babl_component ("Ga"), + babl_component ("Ba"), + babl_component ("A"), + NULL); + const Babl *rgbA16 = babl_format_new ( + babl_model ("RaGaBaA"), + babl_type ("u16"), + babl_component ("Ra"), + babl_component ("Ga"), + babl_component ("Ba"), + babl_component ("A"), + NULL); + const Babl *rgbA8 = babl_format_new ( + babl_model ("RaGaBaA"), + babl_type ("u8"), + babl_component ("Ra"), + babl_component ("Ga"), + babl_component ("Ba"), + babl_component ("A"), + NULL); + const Babl *rgbF = babl_format_new ( + babl_model ("RGB"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgb16 = babl_format_new ( + babl_model ("RGB"), + babl_type ("u16"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgb8 = babl_format_new ( + babl_model ("RGB"), + babl_type ("u8"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *gaF = babl_format_new ( + babl_model ("YA"), + babl_type ("float"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *gAF = babl_format_new ( + babl_model ("YaA"), + babl_type ("float"), + babl_component ("Ya"), + babl_component ("A"), + NULL); + const Babl *gF = babl_format_new ( + babl_model ("Y"), + babl_type ("float"), + babl_component ("Y"), + NULL); + const Babl *ga16 = babl_format_new ( + babl_model ("YA"), + babl_type ("u16"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *gA16 = babl_format_new ( + babl_model ("YaA"), + babl_type ("u16"), + babl_component ("Ya"), + babl_component ("A"), + NULL); + const Babl *g16 = babl_format_new ( + babl_model ("Y"), + babl_type ("u16"), + babl_component ("Y"), + NULL); + const Babl *ga8 = babl_format_new ( + babl_model ("YA"), + babl_type ("u8"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *gA8 = babl_format_new ( + babl_model ("YaA"), + babl_type ("u8"), + babl_component ("Ya"), + babl_component ("A"), + NULL); + const Babl *g8 = babl_format_new ( + babl_model ("Y"), + babl_type ("u8"), + babl_component ("Y"), + NULL); + +#define o(src, dst) \ + babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL) + + o (rgbaF, rgba8); + o (rgba8, rgbaF); + o (rgbaF, rgba16); + o (rgba16, rgbaF); + o (rgbAF, rgbA8); + o (rgbA8, rgbAF); + o (rgbAF, rgbA16); + o (rgbA16, rgbAF); + o (rgbF, rgb8); + o (rgb8, rgbF); + o (rgbF, rgb16); + o (rgb16, rgbF); + o (gaF, ga8); + o (gAF, gA8); + o (gF, g8); + o (ga8, gaF); + o (gA8, gAF); + o (g8, gF); + o (gaF, ga16); + o (gAF, gA16); + o (gF, g16); + o (ga16, gaF); + o (gA16, gAF); + o (g16, gF); + + if (!table_inited) + table_init (); + + return 0; +} diff --git a/extensions/gggl-table.c b/extensions/gggl-table.c new file mode 100644 index 0000000..071167d --- /dev/null +++ b/extensions/gggl-table.c @@ -0,0 +1,528 @@ +/* + * This file was part of gggl, it implements a variety of pixel conversion + * functions that are usable with babl, the file needs more cleanup. + * + * GGGL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GGGL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GGGL; if not, see . + * + * Rights are granted to use this shared object in libraries covered by + * LGPL. (exception added, during import into babl CVS.) + * + * Copyright 2003, 2004, 2005 Øyvind Kolås + */ + +#define _POSIX_C_SOURCE 200112L + +#include "config.h" +#include +#include +#include + +#include "babl.h" +#include "extensions/util.h" + +/* + * Implemented according to information read from: + * + * http://www.cinenet.net/~spitzak/conversion/sketches_0265.pdf + * + * initially ignoring any diffusion, to keep the implementation + * smaller, and interchangeable with the non optimized version. + * + * due to ability to be able to relicence gggl under a different + * licence than GPL, I avoided the temptation to look at the + * source files in the same location, in case I was going to + * need this piece of code for projects where GPL compatibility + * was a must. + * + * TODO: error diffusion, + * gamma correction (not really,. gamma correction belongs in seperate ops,. + */ + +/* lookup tables used in conversion */ + +static float table_8_F[1 << 8]; +static float table_16_F[1 << 16]; +static unsigned char table_F_8[1 << 16]; +static unsigned short table_F_16[1 << 16]; + +static uint32_t *table_8_F_int = NULL; + +static int table_inited = 0; + +static void +table_init (void) +{ + if (table_inited) + return; + + table_8_F_int = (void*)(table_8_F); + + table_inited = 1; + + /* fill tables for conversion from integer to float */ + { + int i; + for (i = 0; i < 1 << 8; i++) + { + table_8_F[i] = (i * 1.0) / 255.0; + } + for (i = 0; i < 1 << 16; i++) + table_16_F[i] = (i * 1.0) / 65535.0; + } + /* fill tables for conversion from float to integer */ + { + union + { + float f; + unsigned short s[2]; + } u; + u.f = 0.0; + + u.s[0] = 0x8000; + + for (u.s[1] = 0; u.s[1] < 65535; u.s[1] += 1) + { + unsigned char c; + unsigned short s; + + if (u.f <= 0.0) + { + c = 0; + s = 0; + } + else if (u.f >= 1.0) + { + c = 255; + s = 65535; + } + else + { + c = lrint (u.f * 255.0); + s = lrint (u.f * 65535.0); + } + + /*fprintf (stderr, "%2.3f=%03i %05i ", f, c, (*hi)); + / if (! ((*hi)%9)) + / fprintf (stderr, "\n"); */ + + table_F_8[u.s[1]] = c; + table_F_16[u.s[1]] = s; + } + } + /* fix tables to ensure 1:1 conversions back and forth */ + if (0) + { /*FIXME: probably not the right way to do it,.. must sit down and scribble on paper */ + int i; + for (i = 0; i < 256; i++) + { + float f = table_8_F[i]; + unsigned short *hi = ((unsigned short *) (void *) &f); + unsigned short *lo = ((unsigned short *) (void *) &f); + *lo = 0; + table_F_8[(*hi)] = i; + } + } +} + +/* function to find the index in table for a float */ +static unsigned int +gggl_float_to_index16 (float f) +{ + union + { + float f; + unsigned short s[2]; + } u; + u.f = f; + return u.s[1]; +} + +static long +conv_F_8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + register float f = (*(float *) src); + *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; + dst += 1; + src += 4; + } + return samples; +} + +static long +conv_F_16 (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + register float f = (*(float *) src); + *(unsigned short *) dst = table_F_16[gggl_float_to_index16 (f)]; + dst += 2; + src += 4; + } + return samples; +} + +static long +conv_8_F (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; + dst += 4; + src += 1; + } + return samples; +} + +static long +conv_rgb8_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; + dst += 4; + src += 1; + (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; + dst += 4; + src += 1; + (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; + dst += 4; + src += 1; + (*(float *) dst) = 1.0; + dst += 4; + } + return samples; +} + +static long +conv_16_F (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + if (!table_inited) + table_init (); + while (n--) + { + (*(float *) dst) = table_16_F[*(unsigned short *) src]; + dst += 4; + src += 2; + } + return samples; +} + +static long +conv_rgbaF_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n = samples; + + while (n--) + { + register float f = (*(float *) src); + *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; + src += 4; + dst += 1; + + f = (*(float *) src); + *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; + src += 4; + dst += 1; + + f = (*(float *) src); + *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; + src += 4; + dst += 1; + + src += 4; + } + return samples; +} + + +/*********/ +static long +conv_rgbaF_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 4); + return samples; +} + +static long +conv_rgbF_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 3); + return samples; +} + +static long +conv_gaF_ga8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbAF_rgbA8 conv_rgbaF_rgba8 +#define conv_gF_g8 conv_F_8 +#define conv_gAF_gA8 conv_gaF_ga8 + +static long +conv_rgbaF_rgba16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 4); + return samples; +} + +static long +conv_rgbF_rgb16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 3); + return samples; +} + +static long +conv_gaF_ga16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbAF_rgbA16 conv_rgbaF_rgba16 +#define conv_gF_g16 conv_F_16 +#define conv_gAF_gA16 conv_gaF_ga16 + +static long +conv_rgba8_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + return conv_8_F (src, dst, samples * 4) / 4; +} + + +static long +conv_rgb8_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + return conv_8_F (src, dst, samples * 3) / 3; +} + +static long +conv_ga8_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + return conv_8_F (src, dst, samples * 2) / 2; +} + +#define conv_rgbA8_rgbAF conv_rgba8_rgbaF +#define conv_gA8_gAF conv_ga8_gaF +#define conv_g8_gF conv_8_F + +static long +conv_rgba16_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 4); + return samples; +} + +static long +conv_rgb16_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 3); + return samples; +} + +static long +conv_ga16_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 2); + return samples; +} + +#define conv_rgbA16_rgbAF conv_rgba16_rgbaF +#define conv_gA16_gAF conv_ga16_gaF +#define conv_g16_gF conv_16_F + +int init (void); + +int +init (void) +{ + const Babl *rgbaF = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgba16 = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("u16"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgba8 = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("u8"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgbAF = babl_format_new ( + babl_model ("R'aG'aB'aA"), + babl_type ("float"), + babl_component ("R'a"), + babl_component ("G'a"), + babl_component ("B'a"), + babl_component ("A"), + NULL); + const Babl *rgbA16 = babl_format_new ( + babl_model ("R'aG'aB'aA"), + babl_type ("u16"), + babl_component ("R'a"), + babl_component ("G'a"), + babl_component ("B'a"), + babl_component ("A"), + NULL); + const Babl *rgbA8 = babl_format_new ( + babl_model ("R'aG'aB'aA"), + babl_type ("u8"), + babl_component ("R'a"), + babl_component ("G'a"), + babl_component ("B'a"), + babl_component ("A"), + NULL); + const Babl *rgbF = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *rgb16 = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("u16"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *rgb8 = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("u8"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *gaF = babl_format_new ( + babl_model ("Y'A"), + babl_type ("float"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *gAF = babl_format_new ( + babl_model ("Y'aA"), + babl_type ("float"), + babl_component ("Y'a"), + babl_component ("A"), + NULL); + const Babl *gF = babl_format_new ( + babl_model ("Y'"), + babl_type ("float"), + babl_component ("Y'"), + NULL); + const Babl *ga16 = babl_format_new ( + babl_model ("Y'A"), + babl_type ("u16"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *gA16 = babl_format_new ( + babl_model ("Y'aA"), + babl_type ("u16"), + babl_component ("Y'a"), + babl_component ("A"), + NULL); + const Babl *g16 = babl_format_new ( + babl_model ("Y'"), + babl_type ("u16"), + babl_component ("Y'"), + NULL); + const Babl *ga8 = babl_format_new ( + babl_model ("Y'A"), + babl_type ("u8"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *gA8 = babl_format_new ( + babl_model ("Y'aA"), + babl_type ("u8"), + babl_component ("Y'a"), + babl_component ("A"), + NULL); + const Babl *g8 = babl_format_new ( + babl_model ("Y'"), + babl_type ("u8"), + babl_component ("Y'"), + NULL); + +#define o(src, dst) \ + babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL) + + o (rgbaF, rgba8); + o (rgba8, rgbaF); + o (rgbaF, rgba16); + o (rgba16, rgbaF); + o (rgbAF, rgbA8); + o (rgbA8, rgbAF); + o (rgbAF, rgbA16); + o (rgbA16, rgbAF); + o (rgbF, rgb8); + o (rgb8, rgbF); + o (rgbF, rgb16); + o (rgb16, rgbF); + o (gaF, ga8); + o (gAF, gA8); + o (gF, g8); + o (ga8, gaF); + o (gA8, gAF); + o (g8, gF); + o (gaF, ga16); + o (gAF, gA16); + o (gF, g16); + o (ga16, gaF); + o (gA16, gAF); + o (g16, gF); + o (rgbaF, rgb8); + o (rgb8, rgbaF); + + if (!table_inited) + table_init (); + + return 0; +} diff --git a/extensions/gggl.c b/extensions/gggl.c index e9fc1d9..7ab4400 100644 --- a/extensions/gggl.c +++ b/extensions/gggl.c @@ -49,227 +49,6 @@ * gamma correction (not really,. gamma correction belongs in seperate ops,. */ -#define USE_TABLES -#ifdef USE_TABLES - -/* lookup tables used in conversion */ - -static float table_8_F[1 << 8]; -static float table_16_F[1 << 16]; -static unsigned char table_F_8[1 << 16]; -static unsigned short table_F_16[1 << 16]; - -static uint32_t *table_8_F_int = NULL; - -static int table_inited = 0; - -static void -table_init (void) -{ - if (table_inited) - return; - - table_8_F_int = (void*)(table_8_F); - - table_inited = 1; - - /* fill tables for conversion from integer to float */ - { - int i; - for (i = 0; i < 1 << 8; i++) - { - table_8_F[i] = (i * 1.0) / 255.0; - } - for (i = 0; i < 1 << 16; i++) - table_16_F[i] = (i * 1.0) / 65535.0; - } - /* fill tables for conversion from float to integer */ - { - union - { - float f; - unsigned short s[2]; - } u; - u.f = 0.0; - - u.s[0] = 0x8000; - - for (u.s[1] = 0; u.s[1] < 65535; u.s[1] += 1) - { - unsigned char c; - unsigned short s; - - if (u.f <= 0.0) - { - c = 0; - s = 0; - } - else if (u.f >= 1.0) - { - c = 255; - s = 65535; - } - else - { - c = lrint (u.f * 255.0); - s = lrint (u.f * 65535.0); - } - - /*fprintf (stderr, "%2.3f=%03i %05i ", f, c, (*hi)); - / if (! ((*hi)%9)) - / fprintf (stderr, "\n"); */ - - table_F_8[u.s[1]] = c; - table_F_16[u.s[1]] = s; - } - } - /* fix tables to ensure 1:1 conversions back and forth */ - if (0) - { /*FIXME: probably not the right way to do it,.. must sit down and scribble on paper */ - int i; - for (i = 0; i < 256; i++) - { - float f = table_8_F[i]; - unsigned short *hi = ((unsigned short *) (void *) &f); - unsigned short *lo = ((unsigned short *) (void *) &f); - *lo = 0; - table_F_8[(*hi)] = i; - } - } -} - -/* function to find the index in table for a float */ -static unsigned int -gggl_float_to_index16 (float f) -{ - union - { - float f; - unsigned short s[2]; - } u; - u.f = f; - return u.s[1]; -} - -static long -conv_F_8 (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - register float f = (*(float *) src); - *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; - dst += 1; - src += 4; - } - return samples; -} - -static long -conv_F_16 (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - register float f = (*(float *) src); - *(unsigned short *) dst = table_F_16[gggl_float_to_index16 (f)]; - dst += 2; - src += 4; - } - return samples; -} - -static long -conv_8_F (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; - dst += 4; - src += 1; - } - return samples; -} - -static long -conv_rgb8_rgbaF (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; - dst += 4; - src += 1; - (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; - dst += 4; - src += 1; - (*(uint32_t *) dst) = table_8_F_int[*(unsigned char *) src]; - dst += 4; - src += 1; - (*(float *) dst) = 1.0; - dst += 4; - } - return samples; -} - -static long -conv_16_F (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - if (!table_inited) - table_init (); - while (n--) - { - (*(float *) dst) = table_16_F[*(unsigned short *) src]; - dst += 4; - src += 2; - } - return samples; -} - -static long -conv_rgbaF_rgb8 (unsigned char *src, unsigned char *dst, long samples) -{ - long n = samples; - - while (n--) - { - register float f = (*(float *) src); - *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; - src += 4; - dst += 1; - - f = (*(float *) src); - *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; - src += 4; - dst += 1; - - f = (*(float *) src); - *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; - src += 4; - dst += 1; - - src += 4; - } - return samples; -} - -#else - static long conv_F_8 (unsigned char *src, unsigned char *dst, long samples) { @@ -370,9 +149,6 @@ conv_rgbaF_rgb8 (unsigned char *src, unsigned char *dst, long samples) return samples; } -#endif - - static long conv_F_D (unsigned char *src, unsigned char *dst, long samples) { @@ -673,7 +449,7 @@ conv_rgbF_rgbaF (unsigned char *src, unsigned char *dst, long samples) *(uint32_t *) dst = (*(uint32_t *) src); src += 4; dst += 4; - *(uint32_t *) dst = 1.0; + *(float *) dst = 1.0; dst += 4; } return samples; @@ -1340,12 +1116,6 @@ init (void) o (rgbA16, rgbaF); o (rgbaF, rgbaD); o (rgbaD, rgbaF); - o (rgb8, rgbaF); - -#ifdef USE_TABLES - if (!table_inited) - table_init (); -#endif return 0; } diff --git a/extensions/sse-half.c b/extensions/sse-half.c new file mode 100644 index 0000000..e20c214 --- /dev/null +++ b/extensions/sse-half.c @@ -0,0 +1,270 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2015 Daniel Sabo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see + * . + */ + +#include "config.h" + +#if defined(USE_SSE4_1) && defined(USE_F16C) && defined(ARCH_X86_64) + +#include + +#include +#include + +#include "babl.h" +#include "babl-cpuaccel.h" +#include "extensions/util.h" + +static inline long +conv_yHalf_yF (const uint16_t *src, float *dst, long samples) +{ + const uint64_t *s_vec; + __v4sf *d_vec; + + long n = samples; + + s_vec = (const uint64_t *)src; + d_vec = (__v4sf *)dst; + + while (n >= 4) + { + __m128i in_val = _mm_insert_epi64((__m128i)_mm_setzero_ps(), *s_vec++, 0); + __v4sf out_val = (__v4sf)_mm_cvtph_ps(in_val); + _mm_storeu_ps((float *)d_vec++, out_val); + n -= 4; + } + + src = (const uint16_t *)s_vec; + dst = (float *)d_vec; + + while (n) + { + __m128i in_val = _mm_insert_epi16((__m128i)_mm_setzero_ps(), *src++, 0); + __v4sf out_val = (__v4sf)_mm_cvtph_ps(in_val); + _mm_store_ss(dst++, out_val); + n -= 1; + } + + return samples; +} + +static long +conv_yaHalf_yaF (const uint16_t *src, float *dst, long samples) +{ + return conv_yHalf_yF (src, dst, samples * 2) / 2; +} + +static long +conv_rgbHalf_rgbF (const uint16_t *src, float *dst, long samples) +{ + return conv_yHalf_yF (src, dst, samples * 3) / 3; +} + +static long +conv_rgbaHalf_rgbaF (const uint16_t *src, float *dst, long samples) +{ + return conv_yHalf_yF (src, dst, samples * 4) / 4; +} + +static inline long +conv_yF_yHalf (const float *src, uint16_t *dst, long samples) +{ + const __v4sf *s_vec; + uint64_t *d_vec; + + long n = samples; + + s_vec = (const __v4sf *)src; + d_vec = (uint64_t *)dst; + + while (n >= 4) + { + __m128 in_val = _mm_loadu_ps((float *)s_vec++); + __m128i out_val = _mm_cvtps_ph(in_val, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + _mm_storel_epi64((__m128i *)d_vec++, out_val); + n -= 4; + } + + src = (const float *)s_vec; + dst = (uint16_t *)d_vec; + + while (n) + { + __m128 in_val = _mm_load_ss(src++); + __m128i out_val = _mm_cvtps_ph(in_val, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + *dst++ = _mm_extract_epi16(out_val, 0); + n -= 1; + } + + return samples; +} + +static long +conv_yaF_yaHalf (const float *src, uint16_t *dst, long samples) +{ + return conv_yF_yHalf (src, dst, samples * 2) / 2; +} + +static long +conv_rgbF_rgbHalf (const float *src, uint16_t *dst, long samples) +{ + return conv_yF_yHalf (src, dst, samples * 3) / 3; +} + +static long +conv_rgbaF_rgbaHalf (const float *src, uint16_t *dst, long samples) +{ + return conv_yF_yHalf (src, dst, samples * 4) / 4; +} + +#endif /* defined(USE_SSE4_1) && defined(USE_F16C) && defined(ARCH_X86_64) */ + +int init (void); + +int +init (void) +{ +#if defined(USE_SSE4_1) && defined(USE_F16C) && defined(ARCH_X86_64) + const Babl *rgbaF_linear = babl_format_new ( + babl_model ("RGBA"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgbaHalf_linear = babl_format_new ( + babl_model ("RGBA"), + babl_type ("half"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgbaF_gamma = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgbaHalf_gamma = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("half"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgbF_linear = babl_format_new ( + babl_model ("RGB"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgbHalf_linear = babl_format_new ( + babl_model ("RGB"), + babl_type ("half"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgbF_gamma = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *rgbHalf_gamma = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("half"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *yaF_linear = babl_format_new ( + babl_model ("YA"), + babl_type ("float"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *yaHalf_linear = babl_format_new ( + babl_model ("YA"), + babl_type ("half"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *yaF_gamma = babl_format_new ( + babl_model ("Y'A"), + babl_type ("float"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *yaHalf_gamma = babl_format_new ( + babl_model ("Y'A"), + babl_type ("half"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *yF_linear = babl_format_new ( + babl_model ("Y"), + babl_type ("float"), + babl_component ("Y"), + NULL); + const Babl *yHalf_linear = babl_format_new ( + babl_model ("Y"), + babl_type ("half"), + babl_component ("Y"), + NULL); + const Babl *yF_gamma = babl_format_new ( + babl_model ("Y'"), + babl_type ("float"), + babl_component ("Y'"), + NULL); + const Babl *yHalf_gamma = babl_format_new ( + babl_model ("Y'"), + babl_type ("half"), + babl_component ("Y'"), + NULL); + +#define CONV(src, dst) \ +{ \ + babl_conversion_new (src ## _linear, dst ## _linear, "linear", conv_ ## src ## _ ## dst, NULL); \ + babl_conversion_new (src ## _gamma, dst ## _gamma, "linear", conv_ ## src ## _ ## dst, NULL); \ +} + + if ((babl_cpu_accel_get_support () & BABL_CPU_ACCEL_X86_SSE4_1) && + (babl_cpu_accel_get_support () & BABL_CPU_ACCEL_X86_F16C)) + { + CONV(rgbaHalf, rgbaF); + CONV(rgbHalf, rgbF); + CONV(yaHalf, yaF); + CONV(yHalf, yF); + CONV(rgbaF, rgbaHalf); + CONV(rgbF, rgbHalf); + CONV(yaF, yaHalf); + CONV(yF, yHalf); + } + +#endif /* defined(USE_SSE4_1) && defined(USE_F16C) && defined(ARCH_X86_64) */ + + return 0; +} + diff --git a/extensions/sse2-float.c b/extensions/sse2-float.c index 97b201b..31b58d1 100644 --- a/extensions/sse2-float.c +++ b/extensions/sse2-float.c @@ -568,6 +568,14 @@ init (void) babl_component ("Ba"), babl_component ("A"), NULL); + const Babl *rgbAF_gamma = babl_format_new ( + babl_model ("R'aG'aB'aA"), + babl_type ("float"), + babl_component ("R'a"), + babl_component ("G'a"), + babl_component ("B'a"), + babl_component ("A"), + NULL); const Babl *rgbaF_gamma = babl_format_new ( babl_model ("R'G'B'A"), babl_type ("float"), @@ -622,6 +630,12 @@ init (void) "linear", conv_rgbaF_linear_rgbAF_linear, NULL); + + babl_conversion_new(rgbaF_gamma, + rgbAF_gamma, + "linear", + conv_rgbaF_linear_rgbAF_linear, + NULL); /* Which of these is faster varies by CPU, and the difference * is big enough that it's worthwhile to include both and @@ -632,6 +646,12 @@ init (void) "linear", conv_rgbAF_linear_rgbaF_linear_shuffle, NULL); + babl_conversion_new(rgbAF_gamma, + rgbaF_gamma, + "linear", + conv_rgbAF_linear_rgbaF_linear_shuffle, + NULL); + babl_conversion_new(rgbAF_linear, rgbaF_linear, "linear", diff --git a/extensions/sse4-int8.c b/extensions/sse4-int8.c new file mode 100644 index 0000000..73f63e3 --- /dev/null +++ b/extensions/sse4-int8.c @@ -0,0 +1,218 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2013 Daniel Sabo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see + * . + */ + +#include "config.h" + +#if defined(USE_SSE4_1) + +/* SSE 4 */ +#include + +#include +#include + +#include "babl.h" +#include "babl-cpuaccel.h" +#include "extensions/util.h" + +static inline long +conv_y8_yF (const uint8_t *src, float *dst, long samples) +{ + const float factor = 1.0f / 255.0f; + const __v4sf factor_vec = {1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f}; + const uint32_t *s_vec; + __v4sf *d_vec; + + long n = samples; + + s_vec = (const uint32_t *)src; + d_vec = (__v4sf *)dst; + + while (n >= 4) + { + __m128i in_val; + __v4sf out_val; + in_val = _mm_insert_epi32 (in_val, *s_vec++, 0); + in_val = _mm_cvtepu8_epi32 (in_val); + out_val = _mm_cvtepi32_ps (in_val) * factor_vec; + _mm_storeu_ps ((float *)d_vec++, out_val); + n -= 4; + } + + src = (const uint8_t *)s_vec; + dst = (float *)d_vec; + + while (n) + { + *dst++ = (float)(*src++) * factor; + n -= 1; + } + + return samples; +} + +static long +conv_ya8_yaF (const uint8_t *src, float *dst, long samples) +{ + return conv_y8_yF (src, dst, samples * 2) / 2; +} + +static long +conv_rgb8_rgbF (const uint8_t *src, float *dst, long samples) +{ + return conv_y8_yF (src, dst, samples * 3) / 3; +} + +static long +conv_rgba8_rgbaF (const uint8_t *src, float *dst, long samples) +{ + return conv_y8_yF (src, dst, samples * 4) / 4; +} + +#endif + +int init (void); + +int +init (void) +{ +#if defined(USE_SSE4_1) + const Babl *rgbaF_linear = babl_format_new ( + babl_model ("RGBA"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgba8_linear = babl_format_new ( + babl_model ("RGBA"), + babl_type ("u8"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgbaF_gamma = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgba8_gamma = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("u8"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgbF_linear = babl_format_new ( + babl_model ("RGB"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgb8_linear = babl_format_new ( + babl_model ("RGB"), + babl_type ("u8"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgbF_gamma = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("float"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *rgb8_gamma = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("u8"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + const Babl *yaF_linear = babl_format_new ( + babl_model ("YA"), + babl_type ("float"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *ya8_linear = babl_format_new ( + babl_model ("YA"), + babl_type ("u8"), + babl_component ("Y"), + babl_component ("A"), + NULL); + const Babl *yaF_gamma = babl_format_new ( + babl_model ("Y'A"), + babl_type ("float"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *ya8_gamma = babl_format_new ( + babl_model ("Y'A"), + babl_type ("u8"), + babl_component ("Y'"), + babl_component ("A"), + NULL); + const Babl *yF_linear = babl_format_new ( + babl_model ("Y"), + babl_type ("float"), + babl_component ("Y"), + NULL); + const Babl *y8_linear = babl_format_new ( + babl_model ("Y"), + babl_type ("u8"), + babl_component ("Y"), + NULL); + const Babl *yF_gamma = babl_format_new ( + babl_model ("Y'"), + babl_type ("float"), + babl_component ("Y'"), + NULL); + const Babl *y8_gamma = babl_format_new ( + babl_model ("Y'"), + babl_type ("u8"), + babl_component ("Y'"), + NULL); + +#define CONV(src, dst) \ +{ \ + babl_conversion_new (src ## _linear, dst ## _linear, "linear", conv_ ## src ## _ ## dst, NULL); \ + babl_conversion_new (src ## _gamma, dst ## _gamma, "linear", conv_ ## src ## _ ## dst, NULL); \ +} + + if ((babl_cpu_accel_get_support () & BABL_CPU_ACCEL_X86_SSE4_1)) + { + CONV(rgba8, rgbaF); + CONV(rgb8, rgbF); + CONV(ya8, yaF); + CONV(y8, yF); + } + +#endif + + return 0; +} + diff --git a/tests/Makefile.in b/tests/Makefile.in index 07c2795..a62ced5 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -586,6 +586,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -629,6 +630,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ diff --git a/tools/Makefile.in b/tools/Makefile.in index 7ab763c..1e0f88a 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -216,6 +216,7 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +F16C_EXTRA_CFLAGS = @F16C_EXTRA_CFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -259,6 +260,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHREXT = @SHREXT@ SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ STRIP = @STRIP@ THREAD_LIB = @THREAD_LIB@ -- 2.30.2